diff --git a/Makefile b/Makefile index 7a64c3434f6..4820fb48be0 100644 --- a/Makefile +++ b/Makefile @@ -10,13 +10,17 @@ sync: generate-protocol-tests: ./gradlew :smithy-typescript-protocol-test-codegen:build rm -rf ./private/smithy-rpcv2-cbor + rm -rf ./private/smithy-rpcv2-cbor-schema cp -r ./smithy-typescript-protocol-test-codegen/build/smithyprojections/smithy-typescript-protocol-test-codegen/smithy-rpcv2-cbor/typescript-codegen ./private/smithy-rpcv2-cbor + cp -r ./smithy-typescript-protocol-test-codegen/build/smithyprojections/smithy-typescript-protocol-test-codegen/smithy-rpcv2-cbor-schema/typescript-codegen ./private/smithy-rpcv2-cbor-schema node ./scripts/post-protocol-test-codegen npx prettier --write ./private/smithy-rpcv2-cbor + npx prettier --write ./private/smithy-rpcv2-cbor-schema yarn test-protocols: (cd ./private/smithy-rpcv2-cbor && npx vitest run --globals) + (cd ./private/smithy-rpcv2-cbor-schema && npx vitest run --globals) test-unit: yarn g:vitest run -c vitest.config.ts diff --git a/private/smithy-rpcv2-cbor-schema/package.json b/private/smithy-rpcv2-cbor-schema/package.json new file mode 100644 index 00000000000..e4138c32a83 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/package.json @@ -0,0 +1,84 @@ +{ + "name": "@smithy/smithy-rpcv2-cbor-schema", + "description": "@smithy/smithy-rpcv2-cbor-schema client", + "version": "1.0.0-alpha.1", + "scripts": { + "build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'", + "build:cjs": "tsc -p tsconfig.cjs.json", + "build:es": "tsc -p tsconfig.es.json", + "build:types": "tsc -p tsconfig.types.json", + "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", + "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo || exit 0", + "prepack": "yarn run clean && yarn run build", + "test": "yarn g:vitest run --passWithNoTests" + }, + "main": "./dist-cjs/index.js", + "types": "./dist-types/index.d.ts", + "module": "./dist-es/index.js", + "sideEffects": false, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/types": "latest", + "@smithy/config-resolver": "workspace:^", + "@smithy/core": "workspace:^", + "@smithy/fetch-http-handler": "workspace:^", + "@smithy/hash-node": "workspace:^", + "@smithy/invalid-dependency": "workspace:^", + "@smithy/middleware-content-length": "workspace:^", + "@smithy/middleware-endpoint": "workspace:^", + "@smithy/middleware-retry": "workspace:^", + "@smithy/middleware-serde": "workspace:^", + "@smithy/middleware-stack": "workspace:^", + "@smithy/node-config-provider": "workspace:^", + "@smithy/node-http-handler": "workspace:^", + "@smithy/protocol-http": "workspace:^", + "@smithy/smithy-client": "workspace:^", + "@smithy/types": "workspace:^", + "@smithy/url-parser": "workspace:^", + "@smithy/util-base64": "workspace:^", + "@smithy/util-body-length-browser": "workspace:^", + "@smithy/util-body-length-node": "workspace:^", + "@smithy/util-defaults-mode-browser": "workspace:^", + "@smithy/util-defaults-mode-node": "workspace:^", + "@smithy/util-endpoints": "workspace:^", + "@smithy/util-middleware": "workspace:^", + "@smithy/util-retry": "workspace:^", + "@smithy/util-utf8": "workspace:^", + "tslib": "^2.6.2" + }, + "devDependencies": { + "@tsconfig/node18": "18.2.4", + "@types/node": "^18.19.69", + "concurrently": "7.0.0", + "downlevel-dts": "0.10.1", + "rimraf": "^3.0.0", + "typescript": "~5.8.3", + "vitest": "2.1.8" + }, + "engines": { + "node": ">=18.0.0" + }, + "typesVersions": { + "<4.0": { + "dist-types/*": [ + "dist-types/ts3.4/*" + ] + } + }, + "files": [ + "dist-*/**" + ], + "author": { + "name": "Smithy team", + "url": "https://smithy.io/" + }, + "license": "Apache-2.0", + "browser": { + "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.browser" + }, + "react-native": { + "./dist-es/runtimeConfig": "./dist-es/runtimeConfig.native" + }, + "private": true +} diff --git a/private/smithy-rpcv2-cbor-schema/src/RpcV2Protocol.ts b/private/smithy-rpcv2-cbor-schema/src/RpcV2Protocol.ts new file mode 100644 index 00000000000..cde70ffa0c1 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/RpcV2Protocol.ts @@ -0,0 +1,305 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClient, RpcV2ProtocolClientConfig } from "./RpcV2ProtocolClient"; +import { + EmptyInputOutputCommand, + EmptyInputOutputCommandInput, + EmptyInputOutputCommandOutput, +} from "./commands/EmptyInputOutputCommand"; +import { Float16Command, Float16CommandInput, Float16CommandOutput } from "./commands/Float16Command"; +import { + FractionalSecondsCommand, + FractionalSecondsCommandInput, + FractionalSecondsCommandOutput, +} from "./commands/FractionalSecondsCommand"; +import { + GreetingWithErrorsCommand, + GreetingWithErrorsCommandInput, + GreetingWithErrorsCommandOutput, +} from "./commands/GreetingWithErrorsCommand"; +import { + NoInputOutputCommand, + NoInputOutputCommandInput, + NoInputOutputCommandOutput, +} from "./commands/NoInputOutputCommand"; +import { + OperationWithDefaultsCommand, + OperationWithDefaultsCommandInput, + OperationWithDefaultsCommandOutput, +} from "./commands/OperationWithDefaultsCommand"; +import { + OptionalInputOutputCommand, + OptionalInputOutputCommandInput, + OptionalInputOutputCommandOutput, +} from "./commands/OptionalInputOutputCommand"; +import { + RecursiveShapesCommand, + RecursiveShapesCommandInput, + RecursiveShapesCommandOutput, +} from "./commands/RecursiveShapesCommand"; +import { + RpcV2CborDenseMapsCommand, + RpcV2CborDenseMapsCommandInput, + RpcV2CborDenseMapsCommandOutput, +} from "./commands/RpcV2CborDenseMapsCommand"; +import { + RpcV2CborListsCommand, + RpcV2CborListsCommandInput, + RpcV2CborListsCommandOutput, +} from "./commands/RpcV2CborListsCommand"; +import { + RpcV2CborSparseMapsCommand, + RpcV2CborSparseMapsCommandInput, + RpcV2CborSparseMapsCommandOutput, +} from "./commands/RpcV2CborSparseMapsCommand"; +import { + SimpleScalarPropertiesCommand, + SimpleScalarPropertiesCommandInput, + SimpleScalarPropertiesCommandOutput, +} from "./commands/SimpleScalarPropertiesCommand"; +import { + SparseNullsOperationCommand, + SparseNullsOperationCommandInput, + SparseNullsOperationCommandOutput, +} from "./commands/SparseNullsOperationCommand"; +import { createAggregatedClient } from "@smithy/smithy-client"; +import { HttpHandlerOptions as __HttpHandlerOptions } from "@smithy/types"; + +const commands = { + EmptyInputOutputCommand, + Float16Command, + FractionalSecondsCommand, + GreetingWithErrorsCommand, + NoInputOutputCommand, + OperationWithDefaultsCommand, + OptionalInputOutputCommand, + RecursiveShapesCommand, + RpcV2CborDenseMapsCommand, + RpcV2CborListsCommand, + RpcV2CborSparseMapsCommand, + SimpleScalarPropertiesCommand, + SparseNullsOperationCommand, +}; + +export interface RpcV2Protocol { + /** + * @see {@link EmptyInputOutputCommand} + */ + emptyInputOutput(): Promise; + emptyInputOutput( + args: EmptyInputOutputCommandInput, + options?: __HttpHandlerOptions + ): Promise; + emptyInputOutput( + args: EmptyInputOutputCommandInput, + cb: (err: any, data?: EmptyInputOutputCommandOutput) => void + ): void; + emptyInputOutput( + args: EmptyInputOutputCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: EmptyInputOutputCommandOutput) => void + ): void; + + /** + * @see {@link Float16Command} + */ + float16(): Promise; + float16(args: Float16CommandInput, options?: __HttpHandlerOptions): Promise; + float16(args: Float16CommandInput, cb: (err: any, data?: Float16CommandOutput) => void): void; + float16( + args: Float16CommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: Float16CommandOutput) => void + ): void; + + /** + * @see {@link FractionalSecondsCommand} + */ + fractionalSeconds(): Promise; + fractionalSeconds( + args: FractionalSecondsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + fractionalSeconds( + args: FractionalSecondsCommandInput, + cb: (err: any, data?: FractionalSecondsCommandOutput) => void + ): void; + fractionalSeconds( + args: FractionalSecondsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: FractionalSecondsCommandOutput) => void + ): void; + + /** + * @see {@link GreetingWithErrorsCommand} + */ + greetingWithErrors(): Promise; + greetingWithErrors( + args: GreetingWithErrorsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + greetingWithErrors( + args: GreetingWithErrorsCommandInput, + cb: (err: any, data?: GreetingWithErrorsCommandOutput) => void + ): void; + greetingWithErrors( + args: GreetingWithErrorsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: GreetingWithErrorsCommandOutput) => void + ): void; + + /** + * @see {@link NoInputOutputCommand} + */ + noInputOutput(): Promise; + noInputOutput(args: NoInputOutputCommandInput, options?: __HttpHandlerOptions): Promise; + noInputOutput(args: NoInputOutputCommandInput, cb: (err: any, data?: NoInputOutputCommandOutput) => void): void; + noInputOutput( + args: NoInputOutputCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: NoInputOutputCommandOutput) => void + ): void; + + /** + * @see {@link OperationWithDefaultsCommand} + */ + operationWithDefaults(): Promise; + operationWithDefaults( + args: OperationWithDefaultsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + operationWithDefaults( + args: OperationWithDefaultsCommandInput, + cb: (err: any, data?: OperationWithDefaultsCommandOutput) => void + ): void; + operationWithDefaults( + args: OperationWithDefaultsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: OperationWithDefaultsCommandOutput) => void + ): void; + + /** + * @see {@link OptionalInputOutputCommand} + */ + optionalInputOutput(): Promise; + optionalInputOutput( + args: OptionalInputOutputCommandInput, + options?: __HttpHandlerOptions + ): Promise; + optionalInputOutput( + args: OptionalInputOutputCommandInput, + cb: (err: any, data?: OptionalInputOutputCommandOutput) => void + ): void; + optionalInputOutput( + args: OptionalInputOutputCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: OptionalInputOutputCommandOutput) => void + ): void; + + /** + * @see {@link RecursiveShapesCommand} + */ + recursiveShapes(): Promise; + recursiveShapes( + args: RecursiveShapesCommandInput, + options?: __HttpHandlerOptions + ): Promise; + recursiveShapes(args: RecursiveShapesCommandInput, cb: (err: any, data?: RecursiveShapesCommandOutput) => void): void; + recursiveShapes( + args: RecursiveShapesCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: RecursiveShapesCommandOutput) => void + ): void; + + /** + * @see {@link RpcV2CborDenseMapsCommand} + */ + rpcV2CborDenseMaps(): Promise; + rpcV2CborDenseMaps( + args: RpcV2CborDenseMapsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + rpcV2CborDenseMaps( + args: RpcV2CborDenseMapsCommandInput, + cb: (err: any, data?: RpcV2CborDenseMapsCommandOutput) => void + ): void; + rpcV2CborDenseMaps( + args: RpcV2CborDenseMapsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: RpcV2CborDenseMapsCommandOutput) => void + ): void; + + /** + * @see {@link RpcV2CborListsCommand} + */ + rpcV2CborLists(): Promise; + rpcV2CborLists( + args: RpcV2CborListsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + rpcV2CborLists(args: RpcV2CborListsCommandInput, cb: (err: any, data?: RpcV2CborListsCommandOutput) => void): void; + rpcV2CborLists( + args: RpcV2CborListsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: RpcV2CborListsCommandOutput) => void + ): void; + + /** + * @see {@link RpcV2CborSparseMapsCommand} + */ + rpcV2CborSparseMaps(): Promise; + rpcV2CborSparseMaps( + args: RpcV2CborSparseMapsCommandInput, + options?: __HttpHandlerOptions + ): Promise; + rpcV2CborSparseMaps( + args: RpcV2CborSparseMapsCommandInput, + cb: (err: any, data?: RpcV2CborSparseMapsCommandOutput) => void + ): void; + rpcV2CborSparseMaps( + args: RpcV2CborSparseMapsCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: RpcV2CborSparseMapsCommandOutput) => void + ): void; + + /** + * @see {@link SimpleScalarPropertiesCommand} + */ + simpleScalarProperties(): Promise; + simpleScalarProperties( + args: SimpleScalarPropertiesCommandInput, + options?: __HttpHandlerOptions + ): Promise; + simpleScalarProperties( + args: SimpleScalarPropertiesCommandInput, + cb: (err: any, data?: SimpleScalarPropertiesCommandOutput) => void + ): void; + simpleScalarProperties( + args: SimpleScalarPropertiesCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: SimpleScalarPropertiesCommandOutput) => void + ): void; + + /** + * @see {@link SparseNullsOperationCommand} + */ + sparseNullsOperation(): Promise; + sparseNullsOperation( + args: SparseNullsOperationCommandInput, + options?: __HttpHandlerOptions + ): Promise; + sparseNullsOperation( + args: SparseNullsOperationCommandInput, + cb: (err: any, data?: SparseNullsOperationCommandOutput) => void + ): void; + sparseNullsOperation( + args: SparseNullsOperationCommandInput, + options: __HttpHandlerOptions, + cb: (err: any, data?: SparseNullsOperationCommandOutput) => void + ): void; +} + +/** + * @public + */ +export class RpcV2Protocol extends RpcV2ProtocolClient implements RpcV2Protocol {} +createAggregatedClient(commands, RpcV2Protocol); diff --git a/private/smithy-rpcv2-cbor-schema/src/RpcV2ProtocolClient.ts b/private/smithy-rpcv2-cbor-schema/src/RpcV2ProtocolClient.ts new file mode 100644 index 00000000000..e6b848ab2db --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/RpcV2ProtocolClient.ts @@ -0,0 +1,301 @@ +// smithy-typescript generated code +import { + HttpAuthSchemeInputConfig, + HttpAuthSchemeResolvedConfig, + defaultRpcV2ProtocolHttpAuthSchemeParametersProvider, + resolveHttpAuthSchemeConfig, +} from "./auth/httpAuthSchemeProvider"; +import { EmptyInputOutputCommandInput, EmptyInputOutputCommandOutput } from "./commands/EmptyInputOutputCommand"; +import { Float16CommandInput, Float16CommandOutput } from "./commands/Float16Command"; +import { FractionalSecondsCommandInput, FractionalSecondsCommandOutput } from "./commands/FractionalSecondsCommand"; +import { GreetingWithErrorsCommandInput, GreetingWithErrorsCommandOutput } from "./commands/GreetingWithErrorsCommand"; +import { NoInputOutputCommandInput, NoInputOutputCommandOutput } from "./commands/NoInputOutputCommand"; +import { + OperationWithDefaultsCommandInput, + OperationWithDefaultsCommandOutput, +} from "./commands/OperationWithDefaultsCommand"; +import { + OptionalInputOutputCommandInput, + OptionalInputOutputCommandOutput, +} from "./commands/OptionalInputOutputCommand"; +import { RecursiveShapesCommandInput, RecursiveShapesCommandOutput } from "./commands/RecursiveShapesCommand"; +import { RpcV2CborDenseMapsCommandInput, RpcV2CborDenseMapsCommandOutput } from "./commands/RpcV2CborDenseMapsCommand"; +import { RpcV2CborListsCommandInput, RpcV2CborListsCommandOutput } from "./commands/RpcV2CborListsCommand"; +import { + RpcV2CborSparseMapsCommandInput, + RpcV2CborSparseMapsCommandOutput, +} from "./commands/RpcV2CborSparseMapsCommand"; +import { + SimpleScalarPropertiesCommandInput, + SimpleScalarPropertiesCommandOutput, +} from "./commands/SimpleScalarPropertiesCommand"; +import { + SparseNullsOperationCommandInput, + SparseNullsOperationCommandOutput, +} from "./commands/SparseNullsOperationCommand"; +import { + ClientInputEndpointParameters, + ClientResolvedEndpointParameters, + EndpointParameters, + resolveClientEndpointParameters, +} from "./endpoint/EndpointParameters"; +import { getRuntimeConfig as __getRuntimeConfig } from "./runtimeConfig"; +import { RuntimeExtension, RuntimeExtensionsConfig, resolveRuntimeExtensions } from "./runtimeExtensions"; +import { + DefaultIdentityProviderConfig, + getHttpAuthSchemeEndpointRuleSetPlugin, + getHttpSigningPlugin, +} from "@smithy/core"; +import { getSchemaSerdePlugin } from "@smithy/core/schema"; +import { getContentLengthPlugin } from "@smithy/middleware-content-length"; +import { EndpointInputConfig, EndpointResolvedConfig, resolveEndpointConfig } from "@smithy/middleware-endpoint"; +import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@smithy/middleware-retry"; +import { HttpHandlerUserInput as __HttpHandlerUserInput } from "@smithy/protocol-http"; +import { + Client as __Client, + DefaultsMode as __DefaultsMode, + SmithyConfiguration as __SmithyConfiguration, + SmithyResolvedConfiguration as __SmithyResolvedConfiguration, +} from "@smithy/smithy-client"; +import { + ClientProtocol, + HttpRequest, + HttpResponse, + BodyLengthCalculator as __BodyLengthCalculator, + CheckOptionalClientConfig as __CheckOptionalClientConfig, + ChecksumConstructor as __ChecksumConstructor, + Decoder as __Decoder, + Encoder as __Encoder, + HashConstructor as __HashConstructor, + HttpHandlerOptions as __HttpHandlerOptions, + Logger as __Logger, + Provider as __Provider, + StreamCollector as __StreamCollector, + UrlParser as __UrlParser, +} from "@smithy/types"; + +export { __Client }; + +/** + * @public + */ +export type ServiceInputTypes = + | EmptyInputOutputCommandInput + | Float16CommandInput + | FractionalSecondsCommandInput + | GreetingWithErrorsCommandInput + | NoInputOutputCommandInput + | OperationWithDefaultsCommandInput + | OptionalInputOutputCommandInput + | RecursiveShapesCommandInput + | RpcV2CborDenseMapsCommandInput + | RpcV2CborListsCommandInput + | RpcV2CborSparseMapsCommandInput + | SimpleScalarPropertiesCommandInput + | SparseNullsOperationCommandInput; + +/** + * @public + */ +export type ServiceOutputTypes = + | EmptyInputOutputCommandOutput + | Float16CommandOutput + | FractionalSecondsCommandOutput + | GreetingWithErrorsCommandOutput + | NoInputOutputCommandOutput + | OperationWithDefaultsCommandOutput + | OptionalInputOutputCommandOutput + | RecursiveShapesCommandOutput + | RpcV2CborDenseMapsCommandOutput + | RpcV2CborListsCommandOutput + | RpcV2CborSparseMapsCommandOutput + | SimpleScalarPropertiesCommandOutput + | SparseNullsOperationCommandOutput; + +/** + * @public + */ +export interface ClientDefaults extends Partial<__SmithyConfiguration<__HttpHandlerOptions>> { + /** + * The HTTP handler to use or its constructor options. Fetch in browser and Https in Nodejs. + */ + requestHandler?: __HttpHandlerUserInput; + + /** + * A constructor for a class implementing the {@link @smithy/types#ChecksumConstructor} interface + * that computes the SHA-256 HMAC or checksum of a string or binary buffer. + * @internal + */ + sha256?: __ChecksumConstructor | __HashConstructor; + + /** + * The function that will be used to convert strings into HTTP endpoints. + * @internal + */ + urlParser?: __UrlParser; + + /** + * A function that can calculate the length of a request body. + * @internal + */ + bodyLengthChecker?: __BodyLengthCalculator; + + /** + * A function that converts a stream into an array of bytes. + * @internal + */ + streamCollector?: __StreamCollector; + + /** + * The function that will be used to convert a base64-encoded string to a byte array. + * @internal + */ + base64Decoder?: __Decoder; + + /** + * The function that will be used to convert binary data to a base64-encoded string. + * @internal + */ + base64Encoder?: __Encoder; + + /** + * The function that will be used to convert a UTF8-encoded string to a byte array. + * @internal + */ + utf8Decoder?: __Decoder; + + /** + * The function that will be used to convert binary data to a UTF-8 encoded string. + * @internal + */ + utf8Encoder?: __Encoder; + + /** + * The runtime environment. + * @internal + */ + runtime?: string; + + /** + * Disable dynamically changing the endpoint of the client based on the hostPrefix + * trait of an operation. + */ + disableHostPrefix?: boolean; + + /** + * Value for how many times a request will be made at most in case of retry. + */ + maxAttempts?: number | __Provider; + + /** + * Specifies which retry algorithm to use. + * @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-smithy-util-retry/Enum/RETRY_MODES/ + * + */ + retryMode?: string | __Provider; + + /** + * Optional logger for logging debug/info/warn/error. + */ + logger?: __Logger; + + /** + * Optional extensions + */ + extensions?: RuntimeExtension[]; + + /** + * The protocol controlling the message type (e.g. HTTP) and format (e.g. JSON) + * may be overridden. A default will always be set by the client. + * Available options depend on the service's supported protocols and will not be validated by + * the client. + * @alpha + * + */ + protocol?: ClientProtocol; + + /** + * The {@link @smithy/smithy-client#DefaultsMode} that will be used to determine how certain default configuration options are resolved in the SDK. + */ + defaultsMode?: __DefaultsMode | __Provider<__DefaultsMode>; +} + +/** + * @public + */ +export type RpcV2ProtocolClientConfigType = Partial<__SmithyConfiguration<__HttpHandlerOptions>> & + ClientDefaults & + RetryInputConfig & + EndpointInputConfig & + HttpAuthSchemeInputConfig & + ClientInputEndpointParameters; +/** + * @public + * + * The configuration interface of RpcV2ProtocolClient class constructor that set the region, credentials and other options. + */ +export interface RpcV2ProtocolClientConfig extends RpcV2ProtocolClientConfigType {} + +/** + * @public + */ +export type RpcV2ProtocolClientResolvedConfigType = __SmithyResolvedConfiguration<__HttpHandlerOptions> & + Required & + RuntimeExtensionsConfig & + RetryResolvedConfig & + EndpointResolvedConfig & + HttpAuthSchemeResolvedConfig & + ClientResolvedEndpointParameters; +/** + * @public + * + * The resolved configuration interface of RpcV2ProtocolClient class. This is resolved and normalized from the {@link RpcV2ProtocolClientConfig | constructor configuration interface}. + */ +export interface RpcV2ProtocolClientResolvedConfig extends RpcV2ProtocolClientResolvedConfigType {} + +/** + * @public + */ +export class RpcV2ProtocolClient extends __Client< + __HttpHandlerOptions, + ServiceInputTypes, + ServiceOutputTypes, + RpcV2ProtocolClientResolvedConfig +> { + /** + * The resolved configuration of RpcV2ProtocolClient class. This is resolved and normalized from the {@link RpcV2ProtocolClientConfig | constructor configuration interface}. + */ + readonly config: RpcV2ProtocolClientResolvedConfig; + + constructor(...[configuration]: __CheckOptionalClientConfig) { + let _config_0 = __getRuntimeConfig(configuration || {}); + super(_config_0 as any); + this.initConfig = _config_0; + let _config_1 = resolveClientEndpointParameters(_config_0); + let _config_2 = resolveRetryConfig(_config_1); + let _config_3 = resolveEndpointConfig(_config_2); + let _config_4 = resolveHttpAuthSchemeConfig(_config_3); + let _config_5 = resolveRuntimeExtensions(_config_4, configuration?.extensions || []); + this.config = _config_5; + this.middlewareStack.use(getSchemaSerdePlugin(this.config)); + this.middlewareStack.use(getRetryPlugin(this.config)); + this.middlewareStack.use(getContentLengthPlugin(this.config)); + this.middlewareStack.use( + getHttpAuthSchemeEndpointRuleSetPlugin(this.config, { + httpAuthSchemeParametersProvider: defaultRpcV2ProtocolHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: async (config: RpcV2ProtocolClientResolvedConfig) => + new DefaultIdentityProviderConfig({}), + }) + ); + this.middlewareStack.use(getHttpSigningPlugin(this.config)); + } + + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy(): void { + super.destroy(); + } +} diff --git a/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthExtensionConfiguration.ts b/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthExtensionConfiguration.ts new file mode 100644 index 00000000000..ef06738c086 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthExtensionConfiguration.ts @@ -0,0 +1,60 @@ +// smithy-typescript generated code +import { RpcV2ProtocolHttpAuthSchemeProvider } from "./httpAuthSchemeProvider"; +import { HttpAuthScheme } from "@smithy/types"; + +/** + * @internal + */ +export interface HttpAuthExtensionConfiguration { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void; + httpAuthSchemes(): HttpAuthScheme[]; + setHttpAuthSchemeProvider(httpAuthSchemeProvider: RpcV2ProtocolHttpAuthSchemeProvider): void; + httpAuthSchemeProvider(): RpcV2ProtocolHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export type HttpAuthRuntimeConfig = Partial<{ + httpAuthSchemes: HttpAuthScheme[]; + httpAuthSchemeProvider: RpcV2ProtocolHttpAuthSchemeProvider; +}>; + +/** + * @internal + */ +export const getHttpAuthExtensionConfiguration = ( + runtimeConfig: HttpAuthRuntimeConfig +): HttpAuthExtensionConfiguration => { + let _httpAuthSchemes = runtimeConfig.httpAuthSchemes!; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider!; + return { + setHttpAuthScheme(httpAuthScheme: HttpAuthScheme): void { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes(): HttpAuthScheme[] { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider: RpcV2ProtocolHttpAuthSchemeProvider): void { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider(): RpcV2ProtocolHttpAuthSchemeProvider { + return _httpAuthSchemeProvider; + }, + }; +}; + +/** + * @internal + */ +export const resolveHttpAuthRuntimeConfig = (config: HttpAuthExtensionConfiguration): HttpAuthRuntimeConfig => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + }; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthSchemeProvider.ts b/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthSchemeProvider.ts new file mode 100644 index 00000000000..d4490b9636d --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/auth/httpAuthSchemeProvider.ts @@ -0,0 +1,127 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig } from "../RpcV2ProtocolClient"; +import { + HandlerExecutionContext, + HttpAuthOption, + HttpAuthScheme, + HttpAuthSchemeParameters, + HttpAuthSchemeParametersProvider, + HttpAuthSchemeProvider, + Provider, +} from "@smithy/types"; +import { getSmithyContext, normalizeProvider } from "@smithy/util-middleware"; + +/** + * @internal + */ +export interface RpcV2ProtocolHttpAuthSchemeParameters extends HttpAuthSchemeParameters {} + +/** + * @internal + */ +export interface RpcV2ProtocolHttpAuthSchemeParametersProvider + extends HttpAuthSchemeParametersProvider< + RpcV2ProtocolClientResolvedConfig, + HandlerExecutionContext, + RpcV2ProtocolHttpAuthSchemeParameters, + object + > {} + +/** + * @internal + */ +export const defaultRpcV2ProtocolHttpAuthSchemeParametersProvider = async ( + config: RpcV2ProtocolClientResolvedConfig, + context: HandlerExecutionContext, + input: object +): Promise => { + return { + operation: getSmithyContext(context).operation as string, + }; +}; + +function createSmithyApiNoAuthHttpAuthOption(authParameters: RpcV2ProtocolHttpAuthSchemeParameters): HttpAuthOption { + return { + schemeId: "smithy.api#noAuth", + }; +} + +/** + * @internal + */ +export interface RpcV2ProtocolHttpAuthSchemeProvider + extends HttpAuthSchemeProvider {} + +/** + * @internal + */ +export const defaultRpcV2ProtocolHttpAuthSchemeProvider: RpcV2ProtocolHttpAuthSchemeProvider = (authParameters) => { + const options: HttpAuthOption[] = []; + switch (authParameters.operation) { + default: { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + } + } + return options; +}; + +/** + * @internal + */ +export interface HttpAuthSchemeInputConfig { + /** + * A comma-separated list of case-sensitive auth scheme names. + * An auth scheme name is a fully qualified auth scheme ID with the namespace prefix trimmed. + * For example, the auth scheme with ID aws.auth#sigv4 is named sigv4. + * @public + */ + authSchemePreference?: string[] | Provider; + + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + httpAuthSchemes?: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + httpAuthSchemeProvider?: RpcV2ProtocolHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export interface HttpAuthSchemeResolvedConfig { + /** + * A comma-separated list of case-sensitive auth scheme names. + * An auth scheme name is a fully qualified auth scheme ID with the namespace prefix trimmed. + * For example, the auth scheme with ID aws.auth#sigv4 is named sigv4. + * @public + */ + readonly authSchemePreference: Provider; + + /** + * Configuration of HttpAuthSchemes for a client which provides default identity providers and signers per auth scheme. + * @internal + */ + readonly httpAuthSchemes: HttpAuthScheme[]; + + /** + * Configuration of an HttpAuthSchemeProvider for a client which resolves which HttpAuthScheme to use. + * @internal + */ + readonly httpAuthSchemeProvider: RpcV2ProtocolHttpAuthSchemeProvider; +} + +/** + * @internal + */ +export const resolveHttpAuthSchemeConfig = ( + config: T & HttpAuthSchemeInputConfig +): T & HttpAuthSchemeResolvedConfig => { + return Object.assign(config, { + authSchemePreference: normalizeProvider(config.authSchemePreference ?? []), + }) as T & HttpAuthSchemeResolvedConfig; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts new file mode 100644 index 00000000000..ec4ae287288 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/EmptyInputOutputCommand.ts @@ -0,0 +1,83 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { EmptyStructure } from "../models/models_0"; +import { EmptyInputOutput } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link EmptyInputOutputCommand}. + */ +export interface EmptyInputOutputCommandInput extends EmptyStructure {} +/** + * @public + * + * The output of {@link EmptyInputOutputCommand}. + */ +export interface EmptyInputOutputCommandOutput extends EmptyStructure, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, EmptyInputOutputCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, EmptyInputOutputCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = {}; + * const command = new EmptyInputOutputCommand(input); + * const response = await client.send(command); + * // {}; + * + * ``` + * + * @param EmptyInputOutputCommandInput - {@link EmptyInputOutputCommandInput} + * @returns {@link EmptyInputOutputCommandOutput} + * @see {@link EmptyInputOutputCommandInput} for command's `input` shape. + * @see {@link EmptyInputOutputCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class EmptyInputOutputCommand extends $Command + .classBuilder< + EmptyInputOutputCommandInput, + EmptyInputOutputCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "EmptyInputOutput", {}) + .n("RpcV2ProtocolClient", "EmptyInputOutputCommand") + .f(void 0, void 0) + .sc(EmptyInputOutput) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: {}; + output: {}; + }; + sdk: { + input: EmptyInputOutputCommandInput; + output: EmptyInputOutputCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts b/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts new file mode 100644 index 00000000000..f278bba49c4 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/Float16Command.ts @@ -0,0 +1,85 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { Float16Output } from "../models/models_0"; +import { Float16 } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link Float16Command}. + */ +export interface Float16CommandInput {} +/** + * @public + * + * The output of {@link Float16Command}. + */ +export interface Float16CommandOutput extends Float16Output, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, Float16Command } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, Float16Command } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = {}; + * const command = new Float16Command(input); + * const response = await client.send(command); + * // { // Float16Output + * // value: Number("double"), + * // }; + * + * ``` + * + * @param Float16CommandInput - {@link Float16CommandInput} + * @returns {@link Float16CommandOutput} + * @see {@link Float16CommandInput} for command's `input` shape. + * @see {@link Float16CommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class Float16Command extends $Command + .classBuilder< + Float16CommandInput, + Float16CommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "Float16", {}) + .n("RpcV2ProtocolClient", "Float16Command") + .f(void 0, void 0) + .sc(Float16) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: {}; + output: Float16Output; + }; + sdk: { + input: Float16CommandInput; + output: Float16CommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts new file mode 100644 index 00000000000..110afadbf73 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/FractionalSecondsCommand.ts @@ -0,0 +1,85 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { FractionalSecondsOutput } from "../models/models_0"; +import { FractionalSeconds } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link FractionalSecondsCommand}. + */ +export interface FractionalSecondsCommandInput {} +/** + * @public + * + * The output of {@link FractionalSecondsCommand}. + */ +export interface FractionalSecondsCommandOutput extends FractionalSecondsOutput, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, FractionalSecondsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, FractionalSecondsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = {}; + * const command = new FractionalSecondsCommand(input); + * const response = await client.send(command); + * // { // FractionalSecondsOutput + * // datetime: new Date("TIMESTAMP"), + * // }; + * + * ``` + * + * @param FractionalSecondsCommandInput - {@link FractionalSecondsCommandInput} + * @returns {@link FractionalSecondsCommandOutput} + * @see {@link FractionalSecondsCommandInput} for command's `input` shape. + * @see {@link FractionalSecondsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class FractionalSecondsCommand extends $Command + .classBuilder< + FractionalSecondsCommandInput, + FractionalSecondsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "FractionalSeconds", {}) + .n("RpcV2ProtocolClient", "FractionalSecondsCommand") + .f(void 0, void 0) + .sc(FractionalSeconds) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: {}; + output: FractionalSecondsOutput; + }; + sdk: { + input: FractionalSecondsCommandInput; + output: FractionalSecondsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts new file mode 100644 index 00000000000..4d0181a3ca8 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/GreetingWithErrorsCommand.ts @@ -0,0 +1,98 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { GreetingWithErrorsOutput } from "../models/models_0"; +import { GreetingWithErrors } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link GreetingWithErrorsCommand}. + */ +export interface GreetingWithErrorsCommandInput {} +/** + * @public + * + * The output of {@link GreetingWithErrorsCommand}. + */ +export interface GreetingWithErrorsCommandOutput extends GreetingWithErrorsOutput, __MetadataBearer {} + +/** + * This operation has three possible return values: + * + * 1. A successful response in the form of GreetingWithErrorsOutput + * 2. An InvalidGreeting error. + * 3. A ComplexError error. + * + * Implementations must be able to successfully take a response and + * properly deserialize successful and error responses. + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, GreetingWithErrorsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, GreetingWithErrorsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = {}; + * const command = new GreetingWithErrorsCommand(input); + * const response = await client.send(command); + * // { // GreetingWithErrorsOutput + * // greeting: "STRING_VALUE", + * // }; + * + * ``` + * + * @param GreetingWithErrorsCommandInput - {@link GreetingWithErrorsCommandInput} + * @returns {@link GreetingWithErrorsCommandOutput} + * @see {@link GreetingWithErrorsCommandInput} for command's `input` shape. + * @see {@link GreetingWithErrorsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link InvalidGreeting} (client fault) + * This error is thrown when an invalid greeting value is provided. + * + * @throws {@link ComplexError} (client fault) + * This error is thrown when a request is invalid. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + * @public + */ +export class GreetingWithErrorsCommand extends $Command + .classBuilder< + GreetingWithErrorsCommandInput, + GreetingWithErrorsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "GreetingWithErrors", {}) + .n("RpcV2ProtocolClient", "GreetingWithErrorsCommand") + .f(void 0, void 0) + .sc(GreetingWithErrors) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: {}; + output: GreetingWithErrorsOutput; + }; + sdk: { + input: GreetingWithErrorsCommandInput; + output: GreetingWithErrorsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts new file mode 100644 index 00000000000..7b5ded6158a --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/NoInputOutputCommand.ts @@ -0,0 +1,82 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { NoInputOutput } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link NoInputOutputCommand}. + */ +export interface NoInputOutputCommandInput {} +/** + * @public + * + * The output of {@link NoInputOutputCommand}. + */ +export interface NoInputOutputCommandOutput extends __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, NoInputOutputCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, NoInputOutputCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = {}; + * const command = new NoInputOutputCommand(input); + * const response = await client.send(command); + * // {}; + * + * ``` + * + * @param NoInputOutputCommandInput - {@link NoInputOutputCommandInput} + * @returns {@link NoInputOutputCommandOutput} + * @see {@link NoInputOutputCommandInput} for command's `input` shape. + * @see {@link NoInputOutputCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class NoInputOutputCommand extends $Command + .classBuilder< + NoInputOutputCommandInput, + NoInputOutputCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "NoInputOutput", {}) + .n("RpcV2ProtocolClient", "NoInputOutputCommand") + .f(void 0, void 0) + .sc(NoInputOutput) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: {}; + output: {}; + }; + sdk: { + input: NoInputOutputCommandInput; + output: NoInputOutputCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts new file mode 100644 index 00000000000..132d4afe8ad --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/OperationWithDefaultsCommand.ts @@ -0,0 +1,151 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { OperationWithDefaultsInput, OperationWithDefaultsOutput } from "../models/models_0"; +import { OperationWithDefaults } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link OperationWithDefaultsCommand}. + */ +export interface OperationWithDefaultsCommandInput extends OperationWithDefaultsInput {} +/** + * @public + * + * The output of {@link OperationWithDefaultsCommand}. + */ +export interface OperationWithDefaultsCommandOutput extends OperationWithDefaultsOutput, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, OperationWithDefaultsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, OperationWithDefaultsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // OperationWithDefaultsInput + * defaults: { // Defaults + * defaultString: "STRING_VALUE", + * defaultBoolean: true || false, + * defaultList: [ // TestStringList + * "STRING_VALUE", + * ], + * defaultTimestamp: new Date("TIMESTAMP"), + * defaultBlob: new Uint8Array(), // e.g. Buffer.from("") or new TextEncoder().encode("") + * defaultByte: 0, // BYTE_VALUE + * defaultShort: Number("short"), + * defaultInteger: Number("int"), + * defaultLong: Number("long"), + * defaultFloat: Number("float"), + * defaultDouble: Number("double"), + * defaultMap: { // TestStringMap + * "": "STRING_VALUE", + * }, + * defaultEnum: "FOO" || "BAR" || "BAZ", + * defaultIntEnum: 1 || 2, + * emptyString: "STRING_VALUE", + * falseBoolean: true || false, + * emptyBlob: new Uint8Array(), // e.g. Buffer.from("") or new TextEncoder().encode("") + * zeroByte: 0, // BYTE_VALUE + * zeroShort: Number("short"), + * zeroInteger: Number("int"), + * zeroLong: Number("long"), + * zeroFloat: Number("float"), + * zeroDouble: Number("double"), + * }, + * clientOptionalDefaults: { // ClientOptionalDefaults + * member: Number("int"), + * }, + * topLevelDefault: "STRING_VALUE", + * otherTopLevelDefault: Number("int"), + * }; + * const command = new OperationWithDefaultsCommand(input); + * const response = await client.send(command); + * // { // OperationWithDefaultsOutput + * // defaultString: "STRING_VALUE", + * // defaultBoolean: true || false, + * // defaultList: [ // TestStringList + * // "STRING_VALUE", + * // ], + * // defaultTimestamp: new Date("TIMESTAMP"), + * // defaultBlob: new Uint8Array(), + * // defaultByte: 0, // BYTE_VALUE + * // defaultShort: Number("short"), + * // defaultInteger: Number("int"), + * // defaultLong: Number("long"), + * // defaultFloat: Number("float"), + * // defaultDouble: Number("double"), + * // defaultMap: { // TestStringMap + * // "": "STRING_VALUE", + * // }, + * // defaultEnum: "FOO" || "BAR" || "BAZ", + * // defaultIntEnum: 1 || 2, + * // emptyString: "STRING_VALUE", + * // falseBoolean: true || false, + * // emptyBlob: new Uint8Array(), + * // zeroByte: 0, // BYTE_VALUE + * // zeroShort: Number("short"), + * // zeroInteger: Number("int"), + * // zeroLong: Number("long"), + * // zeroFloat: Number("float"), + * // zeroDouble: Number("double"), + * // }; + * + * ``` + * + * @param OperationWithDefaultsCommandInput - {@link OperationWithDefaultsCommandInput} + * @returns {@link OperationWithDefaultsCommandOutput} + * @see {@link OperationWithDefaultsCommandInput} for command's `input` shape. + * @see {@link OperationWithDefaultsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link ValidationException} (client fault) + * A standard error for input validation failures. + * This should be thrown by services when a member of the input structure + * falls outside of the modeled or documented constraints. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class OperationWithDefaultsCommand extends $Command + .classBuilder< + OperationWithDefaultsCommandInput, + OperationWithDefaultsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "OperationWithDefaults", {}) + .n("RpcV2ProtocolClient", "OperationWithDefaultsCommand") + .f(void 0, void 0) + .sc(OperationWithDefaults) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: OperationWithDefaultsInput; + output: OperationWithDefaultsOutput; + }; + sdk: { + input: OperationWithDefaultsCommandInput; + output: OperationWithDefaultsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts new file mode 100644 index 00000000000..80d403a3dfd --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/OptionalInputOutputCommand.ts @@ -0,0 +1,87 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { SimpleStructure } from "../models/models_0"; +import { OptionalInputOutput } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link OptionalInputOutputCommand}. + */ +export interface OptionalInputOutputCommandInput extends SimpleStructure {} +/** + * @public + * + * The output of {@link OptionalInputOutputCommand}. + */ +export interface OptionalInputOutputCommandOutput extends SimpleStructure, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, OptionalInputOutputCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, OptionalInputOutputCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // SimpleStructure + * value: "STRING_VALUE", + * }; + * const command = new OptionalInputOutputCommand(input); + * const response = await client.send(command); + * // { // SimpleStructure + * // value: "STRING_VALUE", + * // }; + * + * ``` + * + * @param OptionalInputOutputCommandInput - {@link OptionalInputOutputCommandInput} + * @returns {@link OptionalInputOutputCommandOutput} + * @see {@link OptionalInputOutputCommandInput} for command's `input` shape. + * @see {@link OptionalInputOutputCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class OptionalInputOutputCommand extends $Command + .classBuilder< + OptionalInputOutputCommandInput, + OptionalInputOutputCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "OptionalInputOutput", {}) + .n("RpcV2ProtocolClient", "OptionalInputOutputCommand") + .f(void 0, void 0) + .sc(OptionalInputOutput) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: SimpleStructure; + output: SimpleStructure; + }; + sdk: { + input: OptionalInputOutputCommandInput; + output: OptionalInputOutputCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts new file mode 100644 index 00000000000..2f62bc61309 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RecursiveShapesCommand.ts @@ -0,0 +1,111 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { RecursiveShapesInputOutput } from "../models/models_0"; +import { RecursiveShapes } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link RecursiveShapesCommand}. + */ +export interface RecursiveShapesCommandInput extends RecursiveShapesInputOutput {} +/** + * @public + * + * The output of {@link RecursiveShapesCommand}. + */ +export interface RecursiveShapesCommandOutput extends RecursiveShapesInputOutput, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, RecursiveShapesCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, RecursiveShapesCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // RecursiveShapesInputOutput + * nested: { // RecursiveShapesInputOutputNested1 + * foo: "STRING_VALUE", + * nested: { // RecursiveShapesInputOutputNested2 + * bar: "STRING_VALUE", + * recursiveMember: { + * foo: "STRING_VALUE", + * nested: { + * bar: "STRING_VALUE", + * recursiveMember: "", + * }, + * }, + * }, + * }, + * }; + * const command = new RecursiveShapesCommand(input); + * const response = await client.send(command); + * // { // RecursiveShapesInputOutput + * // nested: { // RecursiveShapesInputOutputNested1 + * // foo: "STRING_VALUE", + * // nested: { // RecursiveShapesInputOutputNested2 + * // bar: "STRING_VALUE", + * // recursiveMember: { + * // foo: "STRING_VALUE", + * // nested: { + * // bar: "STRING_VALUE", + * // recursiveMember: "", + * // }, + * // }, + * // }, + * // }, + * // }; + * + * ``` + * + * @param RecursiveShapesCommandInput - {@link RecursiveShapesCommandInput} + * @returns {@link RecursiveShapesCommandOutput} + * @see {@link RecursiveShapesCommandInput} for command's `input` shape. + * @see {@link RecursiveShapesCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class RecursiveShapesCommand extends $Command + .classBuilder< + RecursiveShapesCommandInput, + RecursiveShapesCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "RecursiveShapes", {}) + .n("RpcV2ProtocolClient", "RecursiveShapesCommand") + .f(void 0, void 0) + .sc(RecursiveShapes) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: RecursiveShapesInputOutput; + output: RecursiveShapesInputOutput; + }; + sdk: { + input: RecursiveShapesCommandInput; + output: RecursiveShapesCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts new file mode 100644 index 00000000000..66ae860c331 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborDenseMapsCommand.ts @@ -0,0 +1,128 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { RpcV2CborDenseMapsInputOutput } from "../models/models_0"; +import { RpcV2CborDenseMaps } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link RpcV2CborDenseMapsCommand}. + */ +export interface RpcV2CborDenseMapsCommandInput extends RpcV2CborDenseMapsInputOutput {} +/** + * @public + * + * The output of {@link RpcV2CborDenseMapsCommand}. + */ +export interface RpcV2CborDenseMapsCommandOutput extends RpcV2CborDenseMapsInputOutput, __MetadataBearer {} + +/** + * The example tests basic map serialization. + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, RpcV2CborDenseMapsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, RpcV2CborDenseMapsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // RpcV2CborDenseMapsInputOutput + * denseStructMap: { // DenseStructMap + * "": { // GreetingStruct + * hi: "STRING_VALUE", + * }, + * }, + * denseNumberMap: { // DenseNumberMap + * "": Number("int"), + * }, + * denseBooleanMap: { // DenseBooleanMap + * "": true || false, + * }, + * denseStringMap: { // DenseStringMap + * "": "STRING_VALUE", + * }, + * denseSetMap: { // DenseSetMap + * "": [ // StringSet + * "STRING_VALUE", + * ], + * }, + * }; + * const command = new RpcV2CborDenseMapsCommand(input); + * const response = await client.send(command); + * // { // RpcV2CborDenseMapsInputOutput + * // denseStructMap: { // DenseStructMap + * // "": { // GreetingStruct + * // hi: "STRING_VALUE", + * // }, + * // }, + * // denseNumberMap: { // DenseNumberMap + * // "": Number("int"), + * // }, + * // denseBooleanMap: { // DenseBooleanMap + * // "": true || false, + * // }, + * // denseStringMap: { // DenseStringMap + * // "": "STRING_VALUE", + * // }, + * // denseSetMap: { // DenseSetMap + * // "": [ // StringSet + * // "STRING_VALUE", + * // ], + * // }, + * // }; + * + * ``` + * + * @param RpcV2CborDenseMapsCommandInput - {@link RpcV2CborDenseMapsCommandInput} + * @returns {@link RpcV2CborDenseMapsCommandOutput} + * @see {@link RpcV2CborDenseMapsCommandInput} for command's `input` shape. + * @see {@link RpcV2CborDenseMapsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link ValidationException} (client fault) + * A standard error for input validation failures. + * This should be thrown by services when a member of the input structure + * falls outside of the modeled or documented constraints. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + * @public + */ +export class RpcV2CborDenseMapsCommand extends $Command + .classBuilder< + RpcV2CborDenseMapsCommandInput, + RpcV2CborDenseMapsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "RpcV2CborDenseMaps", {}) + .n("RpcV2ProtocolClient", "RpcV2CborDenseMapsCommand") + .f(void 0, void 0) + .sc(RpcV2CborDenseMaps) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: RpcV2CborDenseMapsInputOutput; + output: RpcV2CborDenseMapsInputOutput; + }; + sdk: { + input: RpcV2CborDenseMapsCommandInput; + output: RpcV2CborDenseMapsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts new file mode 100644 index 00000000000..e8384b850f3 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborListsCommand.ts @@ -0,0 +1,166 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { RpcV2CborListInputOutput } from "../models/models_0"; +import { RpcV2CborLists } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link RpcV2CborListsCommand}. + */ +export interface RpcV2CborListsCommandInput extends RpcV2CborListInputOutput {} +/** + * @public + * + * The output of {@link RpcV2CborListsCommand}. + */ +export interface RpcV2CborListsCommandOutput extends RpcV2CborListInputOutput, __MetadataBearer {} + +/** + * This test case serializes JSON lists for the following cases for both + * input and output: + * + * 1. Normal lists. + * 2. Normal sets. + * 3. Lists of lists. + * 4. Lists of structures. + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, RpcV2CborListsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, RpcV2CborListsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // RpcV2CborListInputOutput + * stringList: [ // StringList + * "STRING_VALUE", + * ], + * stringSet: [ // StringSet + * "STRING_VALUE", + * ], + * integerList: [ // IntegerList + * Number("int"), + * ], + * booleanList: [ // BooleanList + * true || false, + * ], + * timestampList: [ // TimestampList + * new Date("TIMESTAMP"), + * ], + * enumList: [ // FooEnumList + * "Foo" || "Baz" || "Bar" || "1" || "0", + * ], + * intEnumList: [ // IntegerEnumList + * 1 || 2 || 3, + * ], + * nestedStringList: [ // NestedStringList + * [ + * "STRING_VALUE", + * ], + * ], + * structureList: [ // StructureList + * { // StructureListMember + * a: "STRING_VALUE", + * b: "STRING_VALUE", + * }, + * ], + * blobList: [ // BlobList + * new Uint8Array(), // e.g. Buffer.from("") or new TextEncoder().encode("") + * ], + * }; + * const command = new RpcV2CborListsCommand(input); + * const response = await client.send(command); + * // { // RpcV2CborListInputOutput + * // stringList: [ // StringList + * // "STRING_VALUE", + * // ], + * // stringSet: [ // StringSet + * // "STRING_VALUE", + * // ], + * // integerList: [ // IntegerList + * // Number("int"), + * // ], + * // booleanList: [ // BooleanList + * // true || false, + * // ], + * // timestampList: [ // TimestampList + * // new Date("TIMESTAMP"), + * // ], + * // enumList: [ // FooEnumList + * // "Foo" || "Baz" || "Bar" || "1" || "0", + * // ], + * // intEnumList: [ // IntegerEnumList + * // 1 || 2 || 3, + * // ], + * // nestedStringList: [ // NestedStringList + * // [ + * // "STRING_VALUE", + * // ], + * // ], + * // structureList: [ // StructureList + * // { // StructureListMember + * // a: "STRING_VALUE", + * // b: "STRING_VALUE", + * // }, + * // ], + * // blobList: [ // BlobList + * // new Uint8Array(), + * // ], + * // }; + * + * ``` + * + * @param RpcV2CborListsCommandInput - {@link RpcV2CborListsCommandInput} + * @returns {@link RpcV2CborListsCommandOutput} + * @see {@link RpcV2CborListsCommandInput} for command's `input` shape. + * @see {@link RpcV2CborListsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link ValidationException} (client fault) + * A standard error for input validation failures. + * This should be thrown by services when a member of the input structure + * falls outside of the modeled or documented constraints. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + * @public + */ +export class RpcV2CborListsCommand extends $Command + .classBuilder< + RpcV2CborListsCommandInput, + RpcV2CborListsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "RpcV2CborLists", {}) + .n("RpcV2ProtocolClient", "RpcV2CborListsCommand") + .f(void 0, void 0) + .sc(RpcV2CborLists) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: RpcV2CborListInputOutput; + output: RpcV2CborListInputOutput; + }; + sdk: { + input: RpcV2CborListsCommandInput; + output: RpcV2CborListsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts new file mode 100644 index 00000000000..544a19c85fd --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/RpcV2CborSparseMapsCommand.ts @@ -0,0 +1,128 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { RpcV2CborSparseMapsInputOutput } from "../models/models_0"; +import { RpcV2CborSparseMaps } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link RpcV2CborSparseMapsCommand}. + */ +export interface RpcV2CborSparseMapsCommandInput extends RpcV2CborSparseMapsInputOutput {} +/** + * @public + * + * The output of {@link RpcV2CborSparseMapsCommand}. + */ +export interface RpcV2CborSparseMapsCommandOutput extends RpcV2CborSparseMapsInputOutput, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, RpcV2CborSparseMapsCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, RpcV2CborSparseMapsCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // RpcV2CborSparseMapsInputOutput + * sparseStructMap: { // SparseStructMap + * "": { // GreetingStruct + * hi: "STRING_VALUE", + * }, + * }, + * sparseNumberMap: { // SparseNumberMap + * "": Number("int"), + * }, + * sparseBooleanMap: { // SparseBooleanMap + * "": true || false, + * }, + * sparseStringMap: { // SparseStringMap + * "": "STRING_VALUE", + * }, + * sparseSetMap: { // SparseSetMap + * "": [ // StringSet + * "STRING_VALUE", + * ], + * }, + * }; + * const command = new RpcV2CborSparseMapsCommand(input); + * const response = await client.send(command); + * // { // RpcV2CborSparseMapsInputOutput + * // sparseStructMap: { // SparseStructMap + * // "": { // GreetingStruct + * // hi: "STRING_VALUE", + * // }, + * // }, + * // sparseNumberMap: { // SparseNumberMap + * // "": Number("int"), + * // }, + * // sparseBooleanMap: { // SparseBooleanMap + * // "": true || false, + * // }, + * // sparseStringMap: { // SparseStringMap + * // "": "STRING_VALUE", + * // }, + * // sparseSetMap: { // SparseSetMap + * // "": [ // StringSet + * // "STRING_VALUE", + * // ], + * // }, + * // }; + * + * ``` + * + * @param RpcV2CborSparseMapsCommandInput - {@link RpcV2CborSparseMapsCommandInput} + * @returns {@link RpcV2CborSparseMapsCommandOutput} + * @see {@link RpcV2CborSparseMapsCommandInput} for command's `input` shape. + * @see {@link RpcV2CborSparseMapsCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link ValidationException} (client fault) + * A standard error for input validation failures. + * This should be thrown by services when a member of the input structure + * falls outside of the modeled or documented constraints. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class RpcV2CborSparseMapsCommand extends $Command + .classBuilder< + RpcV2CborSparseMapsCommandInput, + RpcV2CborSparseMapsCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "RpcV2CborSparseMaps", {}) + .n("RpcV2ProtocolClient", "RpcV2CborSparseMapsCommand") + .f(void 0, void 0) + .sc(RpcV2CborSparseMaps) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: RpcV2CborSparseMapsInputOutput; + output: RpcV2CborSparseMapsInputOutput; + }; + sdk: { + input: RpcV2CborSparseMapsCommandInput; + output: RpcV2CborSparseMapsCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts new file mode 100644 index 00000000000..d0f97d91c5a --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/SimpleScalarPropertiesCommand.ts @@ -0,0 +1,105 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { SimpleScalarStructure } from "../models/models_0"; +import { SimpleScalarProperties } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link SimpleScalarPropertiesCommand}. + */ +export interface SimpleScalarPropertiesCommandInput extends SimpleScalarStructure {} +/** + * @public + * + * The output of {@link SimpleScalarPropertiesCommand}. + */ +export interface SimpleScalarPropertiesCommandOutput extends SimpleScalarStructure, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, SimpleScalarPropertiesCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, SimpleScalarPropertiesCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // SimpleScalarStructure + * trueBooleanValue: true || false, + * falseBooleanValue: true || false, + * byteValue: 0, // BYTE_VALUE + * doubleValue: Number("double"), + * floatValue: Number("float"), + * integerValue: Number("int"), + * longValue: Number("long"), + * shortValue: Number("short"), + * stringValue: "STRING_VALUE", + * blobValue: new Uint8Array(), // e.g. Buffer.from("") or new TextEncoder().encode("") + * }; + * const command = new SimpleScalarPropertiesCommand(input); + * const response = await client.send(command); + * // { // SimpleScalarStructure + * // trueBooleanValue: true || false, + * // falseBooleanValue: true || false, + * // byteValue: 0, // BYTE_VALUE + * // doubleValue: Number("double"), + * // floatValue: Number("float"), + * // integerValue: Number("int"), + * // longValue: Number("long"), + * // shortValue: Number("short"), + * // stringValue: "STRING_VALUE", + * // blobValue: new Uint8Array(), + * // }; + * + * ``` + * + * @param SimpleScalarPropertiesCommandInput - {@link SimpleScalarPropertiesCommandInput} + * @returns {@link SimpleScalarPropertiesCommandOutput} + * @see {@link SimpleScalarPropertiesCommandInput} for command's `input` shape. + * @see {@link SimpleScalarPropertiesCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class SimpleScalarPropertiesCommand extends $Command + .classBuilder< + SimpleScalarPropertiesCommandInput, + SimpleScalarPropertiesCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "SimpleScalarProperties", {}) + .n("RpcV2ProtocolClient", "SimpleScalarPropertiesCommand") + .f(void 0, void 0) + .sc(SimpleScalarProperties) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: SimpleScalarStructure; + output: SimpleScalarStructure; + }; + sdk: { + input: SimpleScalarPropertiesCommandInput; + output: SimpleScalarPropertiesCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts b/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts new file mode 100644 index 00000000000..f24c36c69bc --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/SparseNullsOperationCommand.ts @@ -0,0 +1,97 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClientResolvedConfig, ServiceInputTypes, ServiceOutputTypes } from "../RpcV2ProtocolClient"; +import { commonParams } from "../endpoint/EndpointParameters"; +import { SparseNullsOperationInputOutput } from "../models/models_0"; +import { SparseNullsOperation } from "../schemas/schemas"; +import { getEndpointPlugin } from "@smithy/middleware-endpoint"; +import { Command as $Command } from "@smithy/smithy-client"; +import { MetadataBearer as __MetadataBearer } from "@smithy/types"; + +/** + * @public + */ +export type { __MetadataBearer }; +export { $Command }; +/** + * @public + * + * The input for {@link SparseNullsOperationCommand}. + */ +export interface SparseNullsOperationCommandInput extends SparseNullsOperationInputOutput {} +/** + * @public + * + * The output of {@link SparseNullsOperationCommand}. + */ +export interface SparseNullsOperationCommandOutput extends SparseNullsOperationInputOutput, __MetadataBearer {} + +/** + * @public + * + * @example + * Use a bare-bones client and the command you need to make an API call. + * ```javascript + * import { RpcV2ProtocolClient, SparseNullsOperationCommand } from "@smithy/smithy-rpcv2-cbor-schema"; // ES Modules import + * // const { RpcV2ProtocolClient, SparseNullsOperationCommand } = require("@smithy/smithy-rpcv2-cbor-schema"); // CommonJS import + * const client = new RpcV2ProtocolClient(config); + * const input = { // SparseNullsOperationInputOutput + * sparseStringList: [ // SparseStringList + * "STRING_VALUE", + * ], + * sparseStringMap: { // SparseStringMap + * "": "STRING_VALUE", + * }, + * }; + * const command = new SparseNullsOperationCommand(input); + * const response = await client.send(command); + * // { // SparseNullsOperationInputOutput + * // sparseStringList: [ // SparseStringList + * // "STRING_VALUE", + * // ], + * // sparseStringMap: { // SparseStringMap + * // "": "STRING_VALUE", + * // }, + * // }; + * + * ``` + * + * @param SparseNullsOperationCommandInput - {@link SparseNullsOperationCommandInput} + * @returns {@link SparseNullsOperationCommandOutput} + * @see {@link SparseNullsOperationCommandInput} for command's `input` shape. + * @see {@link SparseNullsOperationCommandOutput} for command's `response` shape. + * @see {@link RpcV2ProtocolClientResolvedConfig | config} for RpcV2ProtocolClient's `config` shape. + * + * @throws {@link RpcV2ProtocolServiceException} + *

Base exception class for all service exceptions from RpcV2Protocol service.

+ * + * + */ +export class SparseNullsOperationCommand extends $Command + .classBuilder< + SparseNullsOperationCommandInput, + SparseNullsOperationCommandOutput, + RpcV2ProtocolClientResolvedConfig, + ServiceInputTypes, + ServiceOutputTypes + >() + .ep(commonParams) + .m(function (this: any, Command: any, cs: any, config: RpcV2ProtocolClientResolvedConfig, o: any) { + return [getEndpointPlugin(config, Command.getEndpointParameterInstructions())]; + }) + .s("RpcV2Protocol", "SparseNullsOperation", {}) + .n("RpcV2ProtocolClient", "SparseNullsOperationCommand") + .f(void 0, void 0) + .sc(SparseNullsOperation) + .build() { + /** @internal type navigation helper, not in runtime. */ + protected declare static __types: { + api: { + input: SparseNullsOperationInputOutput; + output: SparseNullsOperationInputOutput; + }; + sdk: { + input: SparseNullsOperationCommandInput; + output: SparseNullsOperationCommandOutput; + }; + }; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/commands/index.ts b/private/smithy-rpcv2-cbor-schema/src/commands/index.ts new file mode 100644 index 00000000000..d9a8bbfef70 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/commands/index.ts @@ -0,0 +1,14 @@ +// smithy-typescript generated code +export * from "./EmptyInputOutputCommand"; +export * from "./Float16Command"; +export * from "./FractionalSecondsCommand"; +export * from "./GreetingWithErrorsCommand"; +export * from "./NoInputOutputCommand"; +export * from "./OperationWithDefaultsCommand"; +export * from "./OptionalInputOutputCommand"; +export * from "./RecursiveShapesCommand"; +export * from "./RpcV2CborDenseMapsCommand"; +export * from "./RpcV2CborListsCommand"; +export * from "./RpcV2CborSparseMapsCommand"; +export * from "./SimpleScalarPropertiesCommand"; +export * from "./SparseNullsOperationCommand"; diff --git a/private/smithy-rpcv2-cbor-schema/src/endpoint/EndpointParameters.ts b/private/smithy-rpcv2-cbor-schema/src/endpoint/EndpointParameters.ts new file mode 100644 index 00000000000..053a6856767 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/endpoint/EndpointParameters.ts @@ -0,0 +1,29 @@ +// smithy-typescript generated code +import { Endpoint, EndpointV2, Provider, EndpointParameters as __EndpointParameters } from "@smithy/types"; + +/** + * @public + */ +export interface ClientInputEndpointParameters { + endpoint?: string | Provider | Endpoint | Provider | EndpointV2 | Provider; +} + +export type ClientResolvedEndpointParameters = ClientInputEndpointParameters & { + defaultSigningName: string; +}; + +export const resolveClientEndpointParameters = ( + options: T & ClientInputEndpointParameters +): T & ClientResolvedEndpointParameters => { + return Object.assign(options, { + defaultSigningName: "", + }); +}; + +export const commonParams = { + endpoint: { type: "builtInParams", name: "endpoint" }, +} as const; + +export interface EndpointParameters extends __EndpointParameters { + endpoint?: string; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/endpoint/endpointResolver.ts b/private/smithy-rpcv2-cbor-schema/src/endpoint/endpointResolver.ts new file mode 100644 index 00000000000..c7fbb6d7f36 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/endpoint/endpointResolver.ts @@ -0,0 +1,22 @@ +// smithy-typescript generated code +import { EndpointParameters } from "./EndpointParameters"; +import { ruleSet } from "./ruleset"; +import { EndpointV2, Logger } from "@smithy/types"; +import { EndpointCache, EndpointParams, resolveEndpoint } from "@smithy/util-endpoints"; + +const cache = new EndpointCache({ + size: 50, + params: ["endpoint"], +}); + +export const defaultEndpointResolver = ( + endpointParams: EndpointParameters, + context: { logger?: Logger } = {} +): EndpointV2 => { + return cache.get(endpointParams as EndpointParams, () => + resolveEndpoint(ruleSet, { + endpointParams: endpointParams as EndpointParams, + logger: context.logger, + }) + ); +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/endpoint/ruleset.ts b/private/smithy-rpcv2-cbor-schema/src/endpoint/ruleset.ts new file mode 100644 index 00000000000..14416a50b26 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/endpoint/ruleset.ts @@ -0,0 +1,38 @@ +// smithy-typescript generated code +import { RuleSetObject } from "@smithy/types"; + +export const ruleSet: RuleSetObject = { + version: "1.0", + parameters: { + endpoint: { + type: "string", + builtIn: "SDK::Endpoint", + documentation: "Endpoint used for making requests. Should be formatted as a URI.", + }, + }, + rules: [ + { + conditions: [ + { + fn: "isSet", + argv: [ + { + ref: "endpoint", + }, + ], + }, + ], + endpoint: { + url: { + ref: "endpoint", + }, + }, + type: "endpoint", + }, + { + conditions: [], + error: "(default endpointRuleSet) endpoint is not set - you must configure an endpoint.", + type: "error", + }, + ], +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/extensionConfiguration.ts b/private/smithy-rpcv2-cbor-schema/src/extensionConfiguration.ts new file mode 100644 index 00000000000..7fa5c7ff1fc --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/extensionConfiguration.ts @@ -0,0 +1,12 @@ +// smithy-typescript generated code +import { HttpAuthExtensionConfiguration } from "./auth/httpAuthExtensionConfiguration"; +import { HttpHandlerExtensionConfiguration } from "@smithy/protocol-http"; +import { DefaultExtensionConfiguration } from "@smithy/types"; + +/** + * @internal + */ +export interface RpcV2ProtocolExtensionConfiguration + extends HttpHandlerExtensionConfiguration, + DefaultExtensionConfiguration, + HttpAuthExtensionConfiguration {} diff --git a/private/smithy-rpcv2-cbor-schema/src/index.ts b/private/smithy-rpcv2-cbor-schema/src/index.ts new file mode 100644 index 00000000000..8a7113aa6bd --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/index.ts @@ -0,0 +1,11 @@ +// smithy-typescript generated code +/* eslint-disable */ +export * from "./RpcV2ProtocolClient"; +export * from "./RpcV2Protocol"; +export { ClientInputEndpointParameters } from "./endpoint/EndpointParameters"; +export type { RuntimeExtension } from "./runtimeExtensions"; +export type { RpcV2ProtocolExtensionConfiguration } from "./extensionConfiguration"; +export * from "./commands"; +export * from "./models"; + +export { RpcV2ProtocolServiceException } from "./models/RpcV2ProtocolServiceException"; diff --git a/private/smithy-rpcv2-cbor-schema/src/models/RpcV2ProtocolServiceException.ts b/private/smithy-rpcv2-cbor-schema/src/models/RpcV2ProtocolServiceException.ts new file mode 100644 index 00000000000..792f7ba0caf --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/models/RpcV2ProtocolServiceException.ts @@ -0,0 +1,24 @@ +// smithy-typescript generated code +import { + ServiceException as __ServiceException, + ServiceExceptionOptions as __ServiceExceptionOptions, +} from "@smithy/smithy-client"; + +export type { __ServiceExceptionOptions }; + +export { __ServiceException }; + +/** + * @public + * + * Base exception class for all service exceptions from RpcV2Protocol service. + */ +export class RpcV2ProtocolServiceException extends __ServiceException { + /** + * @internal + */ + constructor(options: __ServiceExceptionOptions) { + super(options); + Object.setPrototypeOf(this, RpcV2ProtocolServiceException.prototype); + } +} diff --git a/private/smithy-rpcv2-cbor-schema/src/models/index.ts b/private/smithy-rpcv2-cbor-schema/src/models/index.ts new file mode 100644 index 00000000000..9eaceb12865 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/models/index.ts @@ -0,0 +1,2 @@ +// smithy-typescript generated code +export * from "./models_0"; diff --git a/private/smithy-rpcv2-cbor-schema/src/models/models_0.ts b/private/smithy-rpcv2-cbor-schema/src/models/models_0.ts new file mode 100644 index 00000000000..caf9a41e11e --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/models/models_0.ts @@ -0,0 +1,358 @@ +// smithy-typescript generated code +import { RpcV2ProtocolServiceException as __BaseException } from "./RpcV2ProtocolServiceException"; +import { ExceptionOptionType as __ExceptionOptionType } from "@smithy/smithy-client"; + +/** + * Describes one specific validation failure for an input member. + * @public + */ +export interface ValidationExceptionField { + /** + * A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. + * @public + */ + path: string | undefined; + + /** + * A detailed description of the validation failure. + * @public + */ + message: string | undefined; +} + +/** + * A standard error for input validation failures. + * This should be thrown by services when a member of the input structure + * falls outside of the modeled or documented constraints. + * @public + */ +export class ValidationException extends __BaseException { + readonly name: "ValidationException" = "ValidationException"; + readonly $fault: "client" = "client"; + /** + * A list of specific failures encountered while validating the input. + * A member can appear in this list more than once if it failed to satisfy multiple constraints. + * @public + */ + fieldList?: ValidationExceptionField[] | undefined; + + /** + * @internal + */ + constructor(opts: __ExceptionOptionType) { + super({ + name: "ValidationException", + $fault: "client", + ...opts, + }); + Object.setPrototypeOf(this, ValidationException.prototype); + this.fieldList = opts.fieldList; + } +} + +/** + * @public + */ +export interface ClientOptionalDefaults { + member?: number | undefined; +} + +/** + * @public + */ +export interface ComplexNestedErrorData { + Foo?: string | undefined; +} + +/** + * This error is thrown when a request is invalid. + * @public + */ +export class ComplexError extends __BaseException { + readonly name: "ComplexError" = "ComplexError"; + readonly $fault: "client" = "client"; + TopLevel?: string | undefined; + Nested?: ComplexNestedErrorData | undefined; + /** + * @internal + */ + constructor(opts: __ExceptionOptionType) { + super({ + name: "ComplexError", + $fault: "client", + ...opts, + }); + Object.setPrototypeOf(this, ComplexError.prototype); + this.TopLevel = opts.TopLevel; + this.Nested = opts.Nested; + } +} + +/** + * @public + * @enum + */ +export const TestEnum = { + BAR: "BAR", + BAZ: "BAZ", + FOO: "FOO", +} as const; +/** + * @public + */ +export type TestEnum = (typeof TestEnum)[keyof typeof TestEnum]; + +export enum TestIntEnum { + ONE = 1, + TWO = 2, +} + +/** + * @public + */ +export interface Defaults { + defaultString?: string | undefined; + defaultBoolean?: boolean | undefined; + defaultList?: string[] | undefined; + defaultTimestamp?: Date | undefined; + defaultBlob?: Uint8Array | undefined; + defaultByte?: number | undefined; + defaultShort?: number | undefined; + defaultInteger?: number | undefined; + defaultLong?: number | undefined; + defaultFloat?: number | undefined; + defaultDouble?: number | undefined; + defaultMap?: Record | undefined; + defaultEnum?: TestEnum | undefined; + defaultIntEnum?: TestIntEnum | undefined; + emptyString?: string | undefined; + falseBoolean?: boolean | undefined; + emptyBlob?: Uint8Array | undefined; + zeroByte?: number | undefined; + zeroShort?: number | undefined; + zeroInteger?: number | undefined; + zeroLong?: number | undefined; + zeroFloat?: number | undefined; + zeroDouble?: number | undefined; +} + +/** + * @public + */ +export interface GreetingStruct { + hi?: string | undefined; +} + +/** + * @public + */ +export interface EmptyStructure {} + +/** + * @public + */ +export interface Float16Output { + value?: number | undefined; +} + +/** + * @public + */ +export interface FractionalSecondsOutput { + datetime?: Date | undefined; +} + +/** + * @public + */ +export interface GreetingWithErrorsOutput { + greeting?: string | undefined; +} + +/** + * This error is thrown when an invalid greeting value is provided. + * @public + */ +export class InvalidGreeting extends __BaseException { + readonly name: "InvalidGreeting" = "InvalidGreeting"; + readonly $fault: "client" = "client"; + Message?: string | undefined; + /** + * @internal + */ + constructor(opts: __ExceptionOptionType) { + super({ + name: "InvalidGreeting", + $fault: "client", + ...opts, + }); + Object.setPrototypeOf(this, InvalidGreeting.prototype); + this.Message = opts.Message; + } +} + +/** + * @public + */ +export interface OperationWithDefaultsInput { + defaults?: Defaults | undefined; + clientOptionalDefaults?: ClientOptionalDefaults | undefined; + topLevelDefault?: string | undefined; + otherTopLevelDefault?: number | undefined; +} + +/** + * @public + */ +export interface OperationWithDefaultsOutput { + defaultString?: string | undefined; + defaultBoolean?: boolean | undefined; + defaultList?: string[] | undefined; + defaultTimestamp?: Date | undefined; + defaultBlob?: Uint8Array | undefined; + defaultByte?: number | undefined; + defaultShort?: number | undefined; + defaultInteger?: number | undefined; + defaultLong?: number | undefined; + defaultFloat?: number | undefined; + defaultDouble?: number | undefined; + defaultMap?: Record | undefined; + defaultEnum?: TestEnum | undefined; + defaultIntEnum?: TestIntEnum | undefined; + emptyString?: string | undefined; + falseBoolean?: boolean | undefined; + emptyBlob?: Uint8Array | undefined; + zeroByte?: number | undefined; + zeroShort?: number | undefined; + zeroInteger?: number | undefined; + zeroLong?: number | undefined; + zeroFloat?: number | undefined; + zeroDouble?: number | undefined; +} + +/** + * @public + */ +export interface SimpleStructure { + value?: string | undefined; +} + +/** + * @public + */ +export interface RpcV2CborDenseMapsInputOutput { + denseStructMap?: Record | undefined; + denseNumberMap?: Record | undefined; + denseBooleanMap?: Record | undefined; + denseStringMap?: Record | undefined; + denseSetMap?: Record | undefined; +} + +/** + * @public + * @enum + */ +export const FooEnum = { + BAR: "Bar", + BAZ: "Baz", + FOO: "Foo", + ONE: "1", + ZERO: "0", +} as const; +/** + * @public + */ +export type FooEnum = (typeof FooEnum)[keyof typeof FooEnum]; + +export enum IntegerEnum { + A = 1, + B = 2, + C = 3, +} + +/** + * @public + */ +export interface StructureListMember { + a?: string | undefined; + b?: string | undefined; +} + +/** + * @public + */ +export interface RpcV2CborListInputOutput { + stringList?: string[] | undefined; + stringSet?: string[] | undefined; + integerList?: number[] | undefined; + booleanList?: boolean[] | undefined; + timestampList?: Date[] | undefined; + enumList?: FooEnum[] | undefined; + intEnumList?: IntegerEnum[] | undefined; + /** + * A list of lists of strings. + * @public + */ + nestedStringList?: string[][] | undefined; + + structureList?: StructureListMember[] | undefined; + blobList?: Uint8Array[] | undefined; +} + +/** + * @public + */ +export interface RpcV2CborSparseMapsInputOutput { + sparseStructMap?: Record | undefined; + sparseNumberMap?: Record | undefined; + sparseBooleanMap?: Record | undefined; + sparseStringMap?: Record | undefined; + sparseSetMap?: Record | undefined; +} + +/** + * @public + */ +export interface SimpleScalarStructure { + trueBooleanValue?: boolean | undefined; + falseBooleanValue?: boolean | undefined; + byteValue?: number | undefined; + doubleValue?: number | undefined; + floatValue?: number | undefined; + integerValue?: number | undefined; + longValue?: number | undefined; + shortValue?: number | undefined; + stringValue?: string | undefined; + blobValue?: Uint8Array | undefined; +} + +/** + * @public + */ +export interface SparseNullsOperationInputOutput { + sparseStringList?: string[] | undefined; + sparseStringMap?: Record | undefined; +} + +/** + * @public + */ +export interface RecursiveShapesInputOutputNested1 { + foo?: string | undefined; + nested?: RecursiveShapesInputOutputNested2 | undefined; +} + +/** + * @public + */ +export interface RecursiveShapesInputOutputNested2 { + bar?: string | undefined; + recursiveMember?: RecursiveShapesInputOutputNested1 | undefined; +} + +/** + * @public + */ +export interface RecursiveShapesInputOutput { + nested?: RecursiveShapesInputOutputNested1 | undefined; +} diff --git a/private/smithy-rpcv2-cbor-schema/src/protocols/Rpcv2cbor.ts b/private/smithy-rpcv2-cbor-schema/src/protocols/Rpcv2cbor.ts new file mode 100644 index 00000000000..f587c35593c --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/protocols/Rpcv2cbor.ts @@ -0,0 +1,1247 @@ +// smithy-typescript generated code +import { EmptyInputOutputCommandInput, EmptyInputOutputCommandOutput } from "../commands/EmptyInputOutputCommand"; +import { Float16CommandInput, Float16CommandOutput } from "../commands/Float16Command"; +import { FractionalSecondsCommandInput, FractionalSecondsCommandOutput } from "../commands/FractionalSecondsCommand"; +import { GreetingWithErrorsCommandInput, GreetingWithErrorsCommandOutput } from "../commands/GreetingWithErrorsCommand"; +import { NoInputOutputCommandInput, NoInputOutputCommandOutput } from "../commands/NoInputOutputCommand"; +import { + OperationWithDefaultsCommandInput, + OperationWithDefaultsCommandOutput, +} from "../commands/OperationWithDefaultsCommand"; +import { + OptionalInputOutputCommandInput, + OptionalInputOutputCommandOutput, +} from "../commands/OptionalInputOutputCommand"; +import { RecursiveShapesCommandInput, RecursiveShapesCommandOutput } from "../commands/RecursiveShapesCommand"; +import { RpcV2CborDenseMapsCommandInput, RpcV2CborDenseMapsCommandOutput } from "../commands/RpcV2CborDenseMapsCommand"; +import { RpcV2CborListsCommandInput, RpcV2CborListsCommandOutput } from "../commands/RpcV2CborListsCommand"; +import { + RpcV2CborSparseMapsCommandInput, + RpcV2CborSparseMapsCommandOutput, +} from "../commands/RpcV2CborSparseMapsCommand"; +import { + SimpleScalarPropertiesCommandInput, + SimpleScalarPropertiesCommandOutput, +} from "../commands/SimpleScalarPropertiesCommand"; +import { + SparseNullsOperationCommandInput, + SparseNullsOperationCommandOutput, +} from "../commands/SparseNullsOperationCommand"; +import { RpcV2ProtocolServiceException as __BaseException } from "../models/RpcV2ProtocolServiceException"; +import { + ClientOptionalDefaults, + ComplexError, + Defaults, + EmptyStructure, + Float16Output, + FooEnum, + FractionalSecondsOutput, + GreetingStruct, + IntegerEnum, + InvalidGreeting, + OperationWithDefaultsInput, + OperationWithDefaultsOutput, + RecursiveShapesInputOutput, + RecursiveShapesInputOutputNested1, + RecursiveShapesInputOutputNested2, + RpcV2CborDenseMapsInputOutput, + RpcV2CborListInputOutput, + RpcV2CborSparseMapsInputOutput, + SimpleScalarStructure, + SimpleStructure, + SparseNullsOperationInputOutput, + StructureListMember, + ValidationException, +} from "../models/models_0"; +import { + dateToTag as __dateToTag, + buildHttpRpcRequest, + cbor, + checkCborResponse as cr, + loadSmithyRpcV2CborErrorCode, + parseCborBody as parseBody, + parseCborErrorBody as parseErrorBody, +} from "@smithy/core/cbor"; +import { HttpRequest as __HttpRequest, HttpResponse as __HttpResponse } from "@smithy/protocol-http"; +import { + decorateServiceException as __decorateServiceException, + expectBoolean as __expectBoolean, + expectByte as __expectByte, + expectInt32 as __expectInt32, + expectLong as __expectLong, + expectNonNull as __expectNonNull, + expectShort as __expectShort, + expectString as __expectString, + limitedParseDouble as __limitedParseDouble, + limitedParseFloat32 as __limitedParseFloat32, + parseEpochTimestamp as __parseEpochTimestamp, + _json, + collectBody, + take, + withBaseException, +} from "@smithy/smithy-client"; +import { + Endpoint as __Endpoint, + HeaderBag as __HeaderBag, + ResponseMetadata as __ResponseMetadata, + SerdeContext as __SerdeContext, +} from "@smithy/types"; + +/** + * serializeRpcv2cborEmptyInputOutputCommand + */ +export const se_EmptyInputOutputCommand = async ( + input: EmptyInputOutputCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(_json(input)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/EmptyInputOutput", undefined, body); +}; + +/** + * serializeRpcv2cborFloat16Command + */ +export const se_Float16Command = async ( + input: Float16CommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { ...SHARED_HEADERS }; + delete headers["content-type"]; + + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/Float16", undefined, undefined); +}; + +/** + * serializeRpcv2cborFractionalSecondsCommand + */ +export const se_FractionalSecondsCommand = async ( + input: FractionalSecondsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { ...SHARED_HEADERS }; + delete headers["content-type"]; + + return buildHttpRpcRequest( + context, + headers, + "/service/RpcV2Protocol/operation/FractionalSeconds", + undefined, + undefined + ); +}; + +/** + * serializeRpcv2cborGreetingWithErrorsCommand + */ +export const se_GreetingWithErrorsCommand = async ( + input: GreetingWithErrorsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { ...SHARED_HEADERS }; + delete headers["content-type"]; + + return buildHttpRpcRequest( + context, + headers, + "/service/RpcV2Protocol/operation/GreetingWithErrors", + undefined, + undefined + ); +}; + +/** + * serializeRpcv2cborNoInputOutputCommand + */ +export const se_NoInputOutputCommand = async ( + input: NoInputOutputCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = { ...SHARED_HEADERS }; + delete headers["content-type"]; + + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/NoInputOutput", undefined, undefined); +}; + +/** + * serializeRpcv2cborOperationWithDefaultsCommand + */ +export const se_OperationWithDefaultsCommand = async ( + input: OperationWithDefaultsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_OperationWithDefaultsInput(input, context)); + return buildHttpRpcRequest( + context, + headers, + "/service/RpcV2Protocol/operation/OperationWithDefaults", + undefined, + body + ); +}; + +/** + * serializeRpcv2cborOptionalInputOutputCommand + */ +export const se_OptionalInputOutputCommand = async ( + input: OptionalInputOutputCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(_json(input)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/OptionalInputOutput", undefined, body); +}; + +/** + * serializeRpcv2cborRecursiveShapesCommand + */ +export const se_RecursiveShapesCommand = async ( + input: RecursiveShapesCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_RecursiveShapesInputOutput(input, context)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/RecursiveShapes", undefined, body); +}; + +/** + * serializeRpcv2cborRpcV2CborDenseMapsCommand + */ +export const se_RpcV2CborDenseMapsCommand = async ( + input: RpcV2CborDenseMapsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(_json(input)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/RpcV2CborDenseMaps", undefined, body); +}; + +/** + * serializeRpcv2cborRpcV2CborListsCommand + */ +export const se_RpcV2CborListsCommand = async ( + input: RpcV2CborListsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_RpcV2CborListInputOutput(input, context)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/RpcV2CborLists", undefined, body); +}; + +/** + * serializeRpcv2cborRpcV2CborSparseMapsCommand + */ +export const se_RpcV2CborSparseMapsCommand = async ( + input: RpcV2CborSparseMapsCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_RpcV2CborSparseMapsInputOutput(input, context)); + return buildHttpRpcRequest(context, headers, "/service/RpcV2Protocol/operation/RpcV2CborSparseMaps", undefined, body); +}; + +/** + * serializeRpcv2cborSimpleScalarPropertiesCommand + */ +export const se_SimpleScalarPropertiesCommand = async ( + input: SimpleScalarPropertiesCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_SimpleScalarStructure(input, context)); + return buildHttpRpcRequest( + context, + headers, + "/service/RpcV2Protocol/operation/SimpleScalarProperties", + undefined, + body + ); +}; + +/** + * serializeRpcv2cborSparseNullsOperationCommand + */ +export const se_SparseNullsOperationCommand = async ( + input: SparseNullsOperationCommandInput, + context: __SerdeContext +): Promise<__HttpRequest> => { + const headers: __HeaderBag = SHARED_HEADERS; + let body: any; + body = cbor.serialize(se_SparseNullsOperationInputOutput(input, context)); + return buildHttpRpcRequest( + context, + headers, + "/service/RpcV2Protocol/operation/SparseNullsOperation", + undefined, + body + ); +}; + +/** + * deserializeRpcv2cborEmptyInputOutputCommand + */ +export const de_EmptyInputOutputCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = _json(data); + const response: EmptyInputOutputCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborFloat16Command + */ +export const de_Float16Command = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_Float16Output(data, context); + const response: Float16CommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborFractionalSecondsCommand + */ +export const de_FractionalSecondsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_FractionalSecondsOutput(data, context); + const response: FractionalSecondsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborGreetingWithErrorsCommand + */ +export const de_GreetingWithErrorsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = _json(data); + const response: GreetingWithErrorsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborNoInputOutputCommand + */ +export const de_NoInputOutputCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + await collectBody(output.body, context); + const response: NoInputOutputCommandOutput = { + $metadata: deserializeMetadata(output), + }; + return response; +}; + +/** + * deserializeRpcv2cborOperationWithDefaultsCommand + */ +export const de_OperationWithDefaultsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_OperationWithDefaultsOutput(data, context); + const response: OperationWithDefaultsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborOptionalInputOutputCommand + */ +export const de_OptionalInputOutputCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = _json(data); + const response: OptionalInputOutputCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborRecursiveShapesCommand + */ +export const de_RecursiveShapesCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_RecursiveShapesInputOutput(data, context); + const response: RecursiveShapesCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborRpcV2CborDenseMapsCommand + */ +export const de_RpcV2CborDenseMapsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = _json(data); + const response: RpcV2CborDenseMapsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborRpcV2CborListsCommand + */ +export const de_RpcV2CborListsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_RpcV2CborListInputOutput(data, context); + const response: RpcV2CborListsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborRpcV2CborSparseMapsCommand + */ +export const de_RpcV2CborSparseMapsCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_RpcV2CborSparseMapsInputOutput(data, context); + const response: RpcV2CborSparseMapsCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborSimpleScalarPropertiesCommand + */ +export const de_SimpleScalarPropertiesCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_SimpleScalarStructure(data, context); + const response: SimpleScalarPropertiesCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserializeRpcv2cborSparseNullsOperationCommand + */ +export const de_SparseNullsOperationCommand = async ( + output: __HttpResponse, + context: __SerdeContext +): Promise => { + cr(output); + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + + const data: any = await parseBody(output.body, context); + let contents: any = {}; + contents = de_SparseNullsOperationInputOutput(data, context); + const response: SparseNullsOperationCommandOutput = { + $metadata: deserializeMetadata(output), + ...contents, + }; + return response; +}; + +/** + * deserialize_Rpcv2cborCommandError + */ +const de_CommandError = async (output: __HttpResponse, context: __SerdeContext): Promise => { + const parsedOutput: any = { + ...output, + body: await parseErrorBody(output.body, context), + }; + const errorCode = loadSmithyRpcV2CborErrorCode(output, parsedOutput.body); + switch (errorCode) { + case "ComplexError": + case "smithy.protocoltests.rpcv2Cbor#ComplexError": + throw await de_ComplexErrorRes(parsedOutput, context); + case "InvalidGreeting": + case "smithy.protocoltests.rpcv2Cbor#InvalidGreeting": + throw await de_InvalidGreetingRes(parsedOutput, context); + case "ValidationException": + case "smithy.framework#ValidationException": + throw await de_ValidationExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode, + }) as never; + } +}; + +/** + * deserializeRpcv2cborValidationExceptionRes + */ +const de_ValidationExceptionRes = async (parsedOutput: any, context: __SerdeContext): Promise => { + const body = parsedOutput.body; + const deserialized: any = _json(body); + const exception = new ValidationException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized, + }); + return __decorateServiceException(exception, body); +}; + +/** + * deserializeRpcv2cborComplexErrorRes + */ +const de_ComplexErrorRes = async (parsedOutput: any, context: __SerdeContext): Promise => { + const body = parsedOutput.body; + const deserialized: any = _json(body); + const exception = new ComplexError({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized, + }); + return __decorateServiceException(exception, body); +}; + +/** + * deserializeRpcv2cborInvalidGreetingRes + */ +const de_InvalidGreetingRes = async (parsedOutput: any, context: __SerdeContext): Promise => { + const body = parsedOutput.body; + const deserialized: any = _json(body); + const exception = new InvalidGreeting({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized, + }); + return __decorateServiceException(exception, body); +}; + +// se_ClientOptionalDefaults omitted. + +/** + * serializeRpcv2cborDefaults + */ +const se_Defaults = (input: Defaults, context: __SerdeContext): any => { + return take(input, { + defaultBlob: [], + defaultBoolean: [], + defaultByte: [], + defaultDouble: [], + defaultEnum: [], + defaultFloat: [], + defaultIntEnum: [], + defaultInteger: [], + defaultList: _json, + defaultLong: [], + defaultMap: _json, + defaultShort: [], + defaultString: [], + defaultTimestamp: __dateToTag, + emptyBlob: [], + emptyString: [], + falseBoolean: [], + zeroByte: [], + zeroDouble: [], + zeroFloat: [], + zeroInteger: [], + zeroLong: [], + zeroShort: [], + }); +}; + +// se_DenseBooleanMap omitted. + +// se_DenseNumberMap omitted. + +// se_DenseSetMap omitted. + +// se_DenseStringMap omitted. + +// se_DenseStructMap omitted. + +// se_EmptyStructure omitted. + +/** + * serializeRpcv2cborOperationWithDefaultsInput + */ +const se_OperationWithDefaultsInput = (input: OperationWithDefaultsInput, context: __SerdeContext): any => { + return take(input, { + clientOptionalDefaults: _json, + defaults: (_) => se_Defaults(_, context), + otherTopLevelDefault: [], + topLevelDefault: [], + }); +}; + +/** + * serializeRpcv2cborRecursiveShapesInputOutput + */ +const se_RecursiveShapesInputOutput = (input: RecursiveShapesInputOutput, context: __SerdeContext): any => { + return take(input, { + nested: (_) => se_RecursiveShapesInputOutputNested1(_, context), + }); +}; + +/** + * serializeRpcv2cborRecursiveShapesInputOutputNested1 + */ +const se_RecursiveShapesInputOutputNested1 = ( + input: RecursiveShapesInputOutputNested1, + context: __SerdeContext +): any => { + return take(input, { + foo: [], + nested: (_) => se_RecursiveShapesInputOutputNested2(_, context), + }); +}; + +/** + * serializeRpcv2cborRecursiveShapesInputOutputNested2 + */ +const se_RecursiveShapesInputOutputNested2 = ( + input: RecursiveShapesInputOutputNested2, + context: __SerdeContext +): any => { + return take(input, { + bar: [], + recursiveMember: (_) => se_RecursiveShapesInputOutputNested1(_, context), + }); +}; + +// se_RpcV2CborDenseMapsInputOutput omitted. + +/** + * serializeRpcv2cborRpcV2CborListInputOutput + */ +const se_RpcV2CborListInputOutput = (input: RpcV2CborListInputOutput, context: __SerdeContext): any => { + return take(input, { + blobList: (_) => se_BlobList(_, context), + booleanList: _json, + enumList: _json, + intEnumList: _json, + integerList: _json, + nestedStringList: _json, + stringList: _json, + stringSet: _json, + structureList: _json, + timestampList: (_) => se_TimestampList(_, context), + }); +}; + +/** + * serializeRpcv2cborRpcV2CborSparseMapsInputOutput + */ +const se_RpcV2CborSparseMapsInputOutput = (input: RpcV2CborSparseMapsInputOutput, context: __SerdeContext): any => { + return take(input, { + sparseBooleanMap: (_) => se_SparseBooleanMap(_, context), + sparseNumberMap: (_) => se_SparseNumberMap(_, context), + sparseSetMap: (_) => se_SparseSetMap(_, context), + sparseStringMap: (_) => se_SparseStringMap(_, context), + sparseStructMap: (_) => se_SparseStructMap(_, context), + }); +}; + +/** + * serializeRpcv2cborSimpleScalarStructure + */ +const se_SimpleScalarStructure = (input: SimpleScalarStructure, context: __SerdeContext): any => { + return take(input, { + blobValue: [], + byteValue: [], + doubleValue: [], + falseBooleanValue: [], + floatValue: [], + integerValue: [], + longValue: [], + shortValue: [], + stringValue: [], + trueBooleanValue: [], + }); +}; + +// se_SimpleStructure omitted. + +/** + * serializeRpcv2cborSparseBooleanMap + */ +const se_SparseBooleanMap = (input: Record, context: __SerdeContext): any => { + return Object.entries(input).reduce((acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key] = value; + } else { + acc[key] = null as any; + } + + return acc; + }, {}); +}; + +/** + * serializeRpcv2cborSparseNullsOperationInputOutput + */ +const se_SparseNullsOperationInputOutput = (input: SparseNullsOperationInputOutput, context: __SerdeContext): any => { + return take(input, { + sparseStringList: (_) => se_SparseStringList(_, context), + sparseStringMap: (_) => se_SparseStringMap(_, context), + }); +}; + +/** + * serializeRpcv2cborSparseNumberMap + */ +const se_SparseNumberMap = (input: Record, context: __SerdeContext): any => { + return Object.entries(input).reduce((acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key] = value; + } else { + acc[key] = null as any; + } + + return acc; + }, {}); +}; + +/** + * serializeRpcv2cborSparseSetMap + */ +const se_SparseSetMap = (input: Record, context: __SerdeContext): any => { + return Object.entries(input).reduce((acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key] = _json(value); + } else { + acc[key] = null as any; + } + + return acc; + }, {}); +}; + +/** + * serializeRpcv2cborSparseStructMap + */ +const se_SparseStructMap = (input: Record, context: __SerdeContext): any => { + return Object.entries(input).reduce((acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key] = _json(value); + } else { + acc[key] = null as any; + } + + return acc; + }, {}); +}; + +// se_StructureList omitted. + +// se_StructureListMember omitted. + +// se_TestStringList omitted. + +// se_TestStringMap omitted. + +/** + * serializeRpcv2cborBlobList + */ +const se_BlobList = (input: Uint8Array[], context: __SerdeContext): any => { + return input.filter((e: any) => e != null); +}; + +// se_BooleanList omitted. + +// se_FooEnumList omitted. + +// se_GreetingStruct omitted. + +// se_IntegerEnumList omitted. + +// se_IntegerList omitted. + +// se_NestedStringList omitted. + +/** + * serializeRpcv2cborSparseStringList + */ +const se_SparseStringList = (input: string[], context: __SerdeContext): any => { + return input; +}; + +/** + * serializeRpcv2cborSparseStringMap + */ +const se_SparseStringMap = (input: Record, context: __SerdeContext): any => { + return Object.entries(input).reduce((acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key] = value; + } else { + acc[key] = null as any; + } + + return acc; + }, {}); +}; + +// se_StringList omitted. + +// se_StringSet omitted. + +/** + * serializeRpcv2cborTimestampList + */ +const se_TimestampList = (input: Date[], context: __SerdeContext): any => { + return input + .filter((e: any) => e != null) + .map((entry) => { + return __dateToTag(entry); + }); +}; + +// de_ValidationException omitted. + +// de_ValidationExceptionField omitted. + +// de_ValidationExceptionFieldList omitted. + +// de_ComplexError omitted. + +// de_ComplexNestedErrorData omitted. + +// de_DenseBooleanMap omitted. + +// de_DenseNumberMap omitted. + +// de_DenseSetMap omitted. + +// de_DenseStringMap omitted. + +// de_DenseStructMap omitted. + +// de_EmptyStructure omitted. + +/** + * deserializeRpcv2cborFloat16Output + */ +const de_Float16Output = (output: any, context: __SerdeContext): Float16Output => { + return take(output, { + value: __limitedParseDouble, + }) as any; +}; + +/** + * deserializeRpcv2cborFractionalSecondsOutput + */ +const de_FractionalSecondsOutput = (output: any, context: __SerdeContext): FractionalSecondsOutput => { + return take(output, { + datetime: (_: any) => __expectNonNull(__parseEpochTimestamp(_)), + }) as any; +}; + +// de_GreetingWithErrorsOutput omitted. + +// de_InvalidGreeting omitted. + +/** + * deserializeRpcv2cborOperationWithDefaultsOutput + */ +const de_OperationWithDefaultsOutput = (output: any, context: __SerdeContext): OperationWithDefaultsOutput => { + return take(output, { + defaultBlob: [], + defaultBoolean: __expectBoolean, + defaultByte: __expectByte, + defaultDouble: __limitedParseDouble, + defaultEnum: __expectString, + defaultFloat: __limitedParseFloat32, + defaultIntEnum: __expectInt32, + defaultInteger: __expectInt32, + defaultList: _json, + defaultLong: __expectLong, + defaultMap: _json, + defaultShort: __expectShort, + defaultString: __expectString, + defaultTimestamp: (_: any) => __expectNonNull(__parseEpochTimestamp(_)), + emptyBlob: [], + emptyString: __expectString, + falseBoolean: __expectBoolean, + zeroByte: __expectByte, + zeroDouble: __limitedParseDouble, + zeroFloat: __limitedParseFloat32, + zeroInteger: __expectInt32, + zeroLong: __expectLong, + zeroShort: __expectShort, + }) as any; +}; + +/** + * deserializeRpcv2cborRecursiveShapesInputOutput + */ +const de_RecursiveShapesInputOutput = (output: any, context: __SerdeContext): RecursiveShapesInputOutput => { + return take(output, { + nested: (_: any) => de_RecursiveShapesInputOutputNested1(_, context), + }) as any; +}; + +/** + * deserializeRpcv2cborRecursiveShapesInputOutputNested1 + */ +const de_RecursiveShapesInputOutputNested1 = ( + output: any, + context: __SerdeContext +): RecursiveShapesInputOutputNested1 => { + return take(output, { + foo: __expectString, + nested: (_: any) => de_RecursiveShapesInputOutputNested2(_, context), + }) as any; +}; + +/** + * deserializeRpcv2cborRecursiveShapesInputOutputNested2 + */ +const de_RecursiveShapesInputOutputNested2 = ( + output: any, + context: __SerdeContext +): RecursiveShapesInputOutputNested2 => { + return take(output, { + bar: __expectString, + recursiveMember: (_: any) => de_RecursiveShapesInputOutputNested1(_, context), + }) as any; +}; + +// de_RpcV2CborDenseMapsInputOutput omitted. + +/** + * deserializeRpcv2cborRpcV2CborListInputOutput + */ +const de_RpcV2CborListInputOutput = (output: any, context: __SerdeContext): RpcV2CborListInputOutput => { + return take(output, { + blobList: (_: any) => de_BlobList(_, context), + booleanList: _json, + enumList: _json, + intEnumList: _json, + integerList: _json, + nestedStringList: _json, + stringList: _json, + stringSet: _json, + structureList: _json, + timestampList: (_: any) => de_TimestampList(_, context), + }) as any; +}; + +/** + * deserializeRpcv2cborRpcV2CborSparseMapsInputOutput + */ +const de_RpcV2CborSparseMapsInputOutput = (output: any, context: __SerdeContext): RpcV2CborSparseMapsInputOutput => { + return take(output, { + sparseBooleanMap: (_: any) => de_SparseBooleanMap(_, context), + sparseNumberMap: (_: any) => de_SparseNumberMap(_, context), + sparseSetMap: (_: any) => de_SparseSetMap(_, context), + sparseStringMap: (_: any) => de_SparseStringMap(_, context), + sparseStructMap: (_: any) => de_SparseStructMap(_, context), + }) as any; +}; + +/** + * deserializeRpcv2cborSimpleScalarStructure + */ +const de_SimpleScalarStructure = (output: any, context: __SerdeContext): SimpleScalarStructure => { + return take(output, { + blobValue: [], + byteValue: __expectByte, + doubleValue: __limitedParseDouble, + falseBooleanValue: __expectBoolean, + floatValue: __limitedParseFloat32, + integerValue: __expectInt32, + longValue: __expectLong, + shortValue: __expectShort, + stringValue: __expectString, + trueBooleanValue: __expectBoolean, + }) as any; +}; + +// de_SimpleStructure omitted. + +/** + * deserializeRpcv2cborSparseBooleanMap + */ +const de_SparseBooleanMap = (output: any, context: __SerdeContext): Record => { + return Object.entries(output).reduce( + (acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key as string] = __expectBoolean(value) as any; + } else { + acc[key as string] = null as any; + } + return acc; + }, + {} as Record + ); +}; + +/** + * deserializeRpcv2cborSparseNullsOperationInputOutput + */ +const de_SparseNullsOperationInputOutput = (output: any, context: __SerdeContext): SparseNullsOperationInputOutput => { + return take(output, { + sparseStringList: (_: any) => de_SparseStringList(_, context), + sparseStringMap: (_: any) => de_SparseStringMap(_, context), + }) as any; +}; + +/** + * deserializeRpcv2cborSparseNumberMap + */ +const de_SparseNumberMap = (output: any, context: __SerdeContext): Record => { + return Object.entries(output).reduce( + (acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key as string] = __expectInt32(value) as any; + } else { + acc[key as string] = null as any; + } + return acc; + }, + {} as Record + ); +}; + +/** + * deserializeRpcv2cborSparseSetMap + */ +const de_SparseSetMap = (output: any, context: __SerdeContext): Record => { + return Object.entries(output).reduce( + (acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key as string] = _json(value); + } else { + acc[key as string] = null as any; + } + return acc; + }, + {} as Record + ); +}; + +/** + * deserializeRpcv2cborSparseStructMap + */ +const de_SparseStructMap = (output: any, context: __SerdeContext): Record => { + return Object.entries(output).reduce( + (acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key as string] = _json(value); + } else { + acc[key as string] = null as any; + } + return acc; + }, + {} as Record + ); +}; + +// de_StructureList omitted. + +// de_StructureListMember omitted. + +// de_TestStringList omitted. + +// de_TestStringMap omitted. + +/** + * deserializeRpcv2cborBlobList + */ +const de_BlobList = (output: any, context: __SerdeContext): Uint8Array[] => { + const collection = (output || []).filter((e: any) => e != null); + return collection; +}; + +// de_BooleanList omitted. + +// de_FooEnumList omitted. + +// de_GreetingStruct omitted. + +// de_IntegerEnumList omitted. + +// de_IntegerList omitted. + +// de_NestedStringList omitted. + +/** + * deserializeRpcv2cborSparseStringList + */ +const de_SparseStringList = (output: any, context: __SerdeContext): string[] => { + const collection = (output || []).map((entry: any) => { + if (entry === null) { + return null as any; + } + return __expectString(entry) as any; + }); + return collection; +}; + +/** + * deserializeRpcv2cborSparseStringMap + */ +const de_SparseStringMap = (output: any, context: __SerdeContext): Record => { + return Object.entries(output).reduce( + (acc: Record, [key, value]: [string, any]) => { + if (value !== null) { + acc[key as string] = __expectString(value) as any; + } else { + acc[key as string] = null as any; + } + return acc; + }, + {} as Record + ); +}; + +// de_StringList omitted. + +// de_StringSet omitted. + +/** + * deserializeRpcv2cborTimestampList + */ +const de_TimestampList = (output: any, context: __SerdeContext): Date[] => { + const collection = (output || []) + .filter((e: any) => e != null) + .map((entry: any) => { + return __expectNonNull(__parseEpochTimestamp(entry)); + }); + return collection; +}; + +const deserializeMetadata = (output: __HttpResponse): __ResponseMetadata => ({ + httpStatusCode: output.statusCode, + requestId: + output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"], +}); + +const throwDefaultError = withBaseException(__BaseException); +const SHARED_HEADERS: __HeaderBag = { + "content-type": "application/cbor", + "smithy-protocol": "rpc-v2-cbor", + accept: "application/cbor", +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.browser.ts b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.browser.ts new file mode 100644 index 00000000000..6c7d4fa35a0 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.browser.ts @@ -0,0 +1,30 @@ +// smithy-typescript generated code +import { Sha256 } from "@aws-crypto/sha256-browser"; +import { FetchHttpHandler as RequestHandler, streamCollector } from "@smithy/fetch-http-handler"; +import { calculateBodyLength } from "@smithy/util-body-length-browser"; +import { DEFAULT_MAX_ATTEMPTS, DEFAULT_RETRY_MODE } from "@smithy/util-retry"; +import { RpcV2ProtocolClientConfig } from "./RpcV2ProtocolClient"; +import { getRuntimeConfig as getSharedRuntimeConfig } from "./runtimeConfig.shared"; +import { loadConfigsForDefaultMode } from "@smithy/smithy-client"; +import { resolveDefaultsModeConfig } from "@smithy/util-defaults-mode-browser"; + +/** + * @internal + */ +export const getRuntimeConfig = (config: RpcV2ProtocolClientConfig) => { + const defaultsMode = resolveDefaultsModeConfig(config); + const defaultConfigProvider = () => defaultsMode().then(loadConfigsForDefaultMode); + const clientSharedValues = getSharedRuntimeConfig(config); + return { + ...clientSharedValues, + ...config, + runtime: "browser", + defaultsMode, + bodyLengthChecker: config?.bodyLengthChecker ?? calculateBodyLength, + maxAttempts: config?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS, + requestHandler: RequestHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? (async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE), + sha256: config?.sha256 ?? Sha256, + streamCollector: config?.streamCollector ?? streamCollector, + }; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.native.ts b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.native.ts new file mode 100644 index 00000000000..efbf0075ed3 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.native.ts @@ -0,0 +1,17 @@ +// smithy-typescript generated code +import { Sha256 } from "@aws-crypto/sha256-js"; +import { RpcV2ProtocolClientConfig } from "./RpcV2ProtocolClient"; +import { getRuntimeConfig as getBrowserRuntimeConfig } from "./runtimeConfig.browser"; + +/** + * @internal + */ +export const getRuntimeConfig = (config: RpcV2ProtocolClientConfig) => { + const browserDefaults = getBrowserRuntimeConfig(config); + return { + ...browserDefaults, + ...config, + runtime: "react-native", + sha256: config?.sha256 ?? Sha256, + }; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.shared.ts b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.shared.ts new file mode 100644 index 00000000000..8ccd0329ed7 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.shared.ts @@ -0,0 +1,39 @@ +// smithy-typescript generated code +import { defaultRpcV2ProtocolHttpAuthSchemeProvider } from "./auth/httpAuthSchemeProvider"; +import { defaultEndpointResolver } from "./endpoint/endpointResolver"; +import { NoAuthSigner } from "@smithy/core"; +import { SmithyRpcV2CborProtocol } from "@smithy/core/cbor"; +import { NoOpLogger } from "@smithy/smithy-client"; +import { IdentityProviderConfig } from "@smithy/types"; +import { parseUrl } from "@smithy/url-parser"; +import { fromBase64, toBase64 } from "@smithy/util-base64"; +import { fromUtf8, toUtf8 } from "@smithy/util-utf8"; +import { RpcV2ProtocolClientConfig } from "./RpcV2ProtocolClient"; + +/** + * @internal + */ +export const getRuntimeConfig = (config: RpcV2ProtocolClientConfig) => { + return { + apiVersion: "2020-07-14", + base64Decoder: config?.base64Decoder ?? fromBase64, + base64Encoder: config?.base64Encoder ?? toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? defaultRpcV2ProtocolHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc: IdentityProviderConfig) => + ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new NoAuthSigner(), + }, + ], + logger: config?.logger ?? new NoOpLogger(), + protocol: config?.protocol ?? new SmithyRpcV2CborProtocol({ defaultNamespace: "smithy.protocoltests.rpcv2Cbor" }), + urlParser: config?.urlParser ?? parseUrl, + utf8Decoder: config?.utf8Decoder ?? fromUtf8, + utf8Encoder: config?.utf8Encoder ?? toUtf8, + }; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.ts b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.ts new file mode 100644 index 00000000000..3922226f4c9 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/runtimeConfig.ts @@ -0,0 +1,42 @@ +// smithy-typescript generated code +import { Hash } from "@smithy/hash-node"; +import { NODE_MAX_ATTEMPT_CONFIG_OPTIONS, NODE_RETRY_MODE_CONFIG_OPTIONS } from "@smithy/middleware-retry"; +import { loadConfig as loadNodeConfig } from "@smithy/node-config-provider"; +import { NodeHttpHandler as RequestHandler, streamCollector } from "@smithy/node-http-handler"; +import { calculateBodyLength } from "@smithy/util-body-length-node"; +import { DEFAULT_RETRY_MODE } from "@smithy/util-retry"; +import { RpcV2ProtocolClientConfig } from "./RpcV2ProtocolClient"; +import { getRuntimeConfig as getSharedRuntimeConfig } from "./runtimeConfig.shared"; +import { loadConfigsForDefaultMode } from "@smithy/smithy-client"; +import { resolveDefaultsModeConfig } from "@smithy/util-defaults-mode-node"; +import { emitWarningIfUnsupportedVersion } from "@smithy/smithy-client"; + +/** + * @internal + */ +export const getRuntimeConfig = (config: RpcV2ProtocolClientConfig) => { + emitWarningIfUnsupportedVersion(process.version); + const defaultsMode = resolveDefaultsModeConfig(config); + const defaultConfigProvider = () => defaultsMode().then(loadConfigsForDefaultMode); + const clientSharedValues = getSharedRuntimeConfig(config); + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + bodyLengthChecker: config?.bodyLengthChecker ?? calculateBodyLength, + maxAttempts: config?.maxAttempts ?? loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + requestHandler: RequestHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: + config?.retryMode ?? + loadNodeConfig( + { + ...NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE, + }, + config + ), + sha256: config?.sha256 ?? Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? streamCollector, + }; +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/runtimeExtensions.ts b/private/smithy-rpcv2-cbor-schema/src/runtimeExtensions.ts new file mode 100644 index 00000000000..22f43123e01 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/runtimeExtensions.ts @@ -0,0 +1,39 @@ +// smithy-typescript generated code +import { getHttpAuthExtensionConfiguration, resolveHttpAuthRuntimeConfig } from "./auth/httpAuthExtensionConfiguration"; +import { getHttpHandlerExtensionConfiguration, resolveHttpHandlerRuntimeConfig } from "@smithy/protocol-http"; +import { getDefaultExtensionConfiguration, resolveDefaultRuntimeConfig } from "@smithy/smithy-client"; +import { RpcV2ProtocolExtensionConfiguration } from "./extensionConfiguration"; + +/** + * @public + */ +export interface RuntimeExtension { + configure(extensionConfiguration: RpcV2ProtocolExtensionConfiguration): void; +} + +/** + * @public + */ +export interface RuntimeExtensionsConfig { + extensions: RuntimeExtension[]; +} + +/** + * @internal + */ +export const resolveRuntimeExtensions = (runtimeConfig: any, extensions: RuntimeExtension[]) => { + const extensionConfiguration: RpcV2ProtocolExtensionConfiguration = Object.assign( + getDefaultExtensionConfiguration(runtimeConfig), + getHttpHandlerExtensionConfiguration(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + + return Object.assign( + runtimeConfig, + resolveDefaultRuntimeConfig(extensionConfiguration), + resolveHttpHandlerRuntimeConfig(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}; diff --git a/private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts new file mode 100644 index 00000000000..958886efe11 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/src/schemas/schemas.ts @@ -0,0 +1,526 @@ +const _B = "Boolean"; +const _BL = "BooleanList"; +const _BLl = "BlobList"; +const _Bl = "Blob"; +const _By = "Byte"; +const _CE = "ComplexError"; +const _CNED = "ComplexNestedErrorData"; +const _COD = "ClientOptionalDefaults"; +const _D = "Double"; +const _DBM = "DenseBooleanMap"; +const _DNM = "DenseNumberMap"; +const _DSM = "DenseStringMap"; +const _DSMe = "DenseSetMap"; +const _DSMen = "DenseStructMap"; +const _DT = "DateTime"; +const _De = "Defaults"; +const _EIO = "EmptyInputOutput"; +const _ES = "EmptyStructure"; +const _F = "Float"; +const _FE = "FooEnum"; +const _FEL = "FooEnumList"; +const _FO = "Float16Output"; +const _FS = "FractionalSeconds"; +const _FSO = "FractionalSecondsOutput"; +const _Fl = "Float16"; +const _Fo = "Foo"; +const _GS = "GreetingStruct"; +const _GWE = "GreetingWithErrors"; +const _GWEO = "GreetingWithErrorsOutput"; +const _I = "Integer"; +const _IE = "IntegerEnum"; +const _IEL = "IntegerEnumList"; +const _IG = "InvalidGreeting"; +const _IL = "IntegerList"; +const _L = "Long"; +const _M = "Message"; +const _N = "Nested"; +const _NIO = "NoInputOutput"; +const _NSL = "NestedStringList"; +const _OIO = "OptionalInputOutput"; +const _OWD = "OperationWithDefaults"; +const _OWDI = "OperationWithDefaultsInput"; +const _OWDO = "OperationWithDefaultsOutput"; +const _RS = "RecursiveShapes"; +const _RSIO = "RecursiveShapesInputOutput"; +const _RSION = "RecursiveShapesInputOutputNested1"; +const _RSIONe = "RecursiveShapesInputOutputNested2"; +const _RVCDM = "RpcV2CborDenseMaps"; +const _RVCDMIO = "RpcV2CborDenseMapsInputOutput"; +const _RVCL = "RpcV2CborLists"; +const _RVCLIO = "RpcV2CborListInputOutput"; +const _RVCSM = "RpcV2CborSparseMaps"; +const _RVCSMIO = "RpcV2CborSparseMapsInputOutput"; +const _S = "String"; +const _SBM = "SparseBooleanMap"; +const _SL = "StringList"; +const _SLM = "StructureListMember"; +const _SLt = "StructureList"; +const _SNM = "SparseNumberMap"; +const _SNO = "SparseNullsOperation"; +const _SNOIO = "SparseNullsOperationInputOutput"; +const _SS = "StringSet"; +const _SSL = "SparseStringList"; +const _SSM = "SparseStringMap"; +const _SSMp = "SparseSetMap"; +const _SSMpa = "SparseStructMap"; +const _SSP = "SimpleScalarProperties"; +const _SSS = "SimpleScalarStructure"; +const _SSi = "SimpleStructure"; +const _Sh = "Short"; +const _T = "Timestamp"; +const _TE = "TestEnum"; +const _TIE = "TestIntEnum"; +const _TL = "TimestampList"; +const _TLo = "TopLevel"; +const _TSL = "TestStringList"; +const _TSM = "TestStringMap"; +const _VE = "ValidationException"; +const _VEF = "ValidationExceptionField"; +const _VEFL = "ValidationExceptionFieldList"; +const _a = "a"; +const _b = "bar"; +const _bL = "booleanList"; +const _bLl = "blobList"; +const _bV = "byteValue"; +const _bVl = "blobValue"; +const _b_ = "b"; +const _c = "client"; +const _cOD = "clientOptionalDefaults"; +const _d = "datetime"; +const _dB = "defaultBoolean"; +const _dBM = "denseBooleanMap"; +const _dBe = "defaultBlob"; +const _dBef = "defaultByte"; +const _dD = "defaultDouble"; +const _dE = "defaultEnum"; +const _dF = "defaultFloat"; +const _dI = "defaultInteger"; +const _dIE = "defaultIntEnum"; +const _dL = "defaultList"; +const _dLe = "defaultLong"; +const _dM = "defaultMap"; +const _dNM = "denseNumberMap"; +const _dS = "defaultString"; +const _dSM = "denseStructMap"; +const _dSMe = "denseStringMap"; +const _dSMen = "denseSetMap"; +const _dSe = "defaultShort"; +const _dT = "defaultTimestamp"; +const _dV = "doubleValue"; +const _de = "defaults"; +const _e = "error"; +const _eB = "emptyBlob"; +const _eL = "enumList"; +const _eS = "emptyString"; +const _f = "foo"; +const _fB = "falseBoolean"; +const _fBV = "falseBooleanValue"; +const _fL = "fieldList"; +const _fV = "floatValue"; +const _g = "greeting"; +const _h = "hi"; +const _iEL = "intEnumList"; +const _iL = "integerList"; +const _iV = "integerValue"; +const _lV = "longValue"; +const _m = "message"; +const _me = "member"; +const _n = "nested"; +const _nSL = "nestedStringList"; +const _oTLD = "otherTopLevelDefault"; +const _p = "path"; +const _rM = "recursiveMember"; +const _s = "sparse"; +const _sBM = "sparseBooleanMap"; +const _sL = "stringList"; +const _sLt = "structureList"; +const _sNM = "sparseNumberMap"; +const _sS = "stringSet"; +const _sSL = "sparseStringList"; +const _sSM = "sparseStructMap"; +const _sSMp = "sparseStringMap"; +const _sSMpa = "sparseSetMap"; +const _sV = "shortValue"; +const _sVt = "stringValue"; +const _tBV = "trueBooleanValue"; +const _tL = "timestampList"; +const _tLD = "topLevelDefault"; +const _v = "value"; +const _zB = "zeroByte"; +const _zD = "zeroDouble"; +const _zF = "zeroFloat"; +const _zI = "zeroInteger"; +const _zL = "zeroLong"; +const _zS = "zeroShort"; +const n0 = "smithy.framework"; +const n1 = "smithy.protocoltests.rpcv2Cbor"; +const n2 = "smithy.protocoltests.shared"; + +// smithy-typescript generated code +import { RpcV2ProtocolServiceException as __RpcV2ProtocolServiceException } from "../models/RpcV2ProtocolServiceException"; +import { + ComplexError as __ComplexError, + InvalidGreeting as __InvalidGreeting, + ValidationException as __ValidationException, +} from "../models/index"; +import { error, list, map, op, struct } from "@smithy/core/schema"; + +/* eslint no-var: 0 */ + +export var Unit = "unit" as const; + +export var ValidationException = error( + n0, + _VE, + { + [_e]: _c, + }, + [_m, _fL], + [0, () => ValidationExceptionFieldList], + + __ValidationException +); +export var ValidationExceptionField = struct(n0, _VEF, 0, [_p, _m], [0, 0]); +export var ClientOptionalDefaults = struct(n1, _COD, 0, [_me], [1]); +export var ComplexError = error( + n1, + _CE, + { + [_e]: _c, + }, + [_TLo, _N], + [0, () => ComplexNestedErrorData], + + __ComplexError +); +export var ComplexNestedErrorData = struct(n1, _CNED, 0, [_Fo], [0]); +export var Defaults = struct( + n1, + _De, + 0, + [ + _dS, + _dB, + _dL, + _dT, + _dBe, + _dBef, + _dSe, + _dI, + _dLe, + _dF, + _dD, + _dM, + _dE, + _dIE, + _eS, + _fB, + _eB, + _zB, + _zS, + _zI, + _zL, + _zF, + _zD, + ], + [0, 2, 64 | 0, 4, 21, 1, 1, 1, 1, 1, 1, 128 | 0, 0, 1, 0, 2, 21, 1, 1, 1, 1, 1, 1] +); +export var EmptyStructure = struct(n1, _ES, 0, [], []); +export var Float16Output = struct(n1, _FO, 0, [_v], [1]); +export var FractionalSecondsOutput = struct(n1, _FSO, 0, [_d], [5]); +export var GreetingWithErrorsOutput = struct(n1, _GWEO, 0, [_g], [0]); +export var InvalidGreeting = error( + n1, + _IG, + { + [_e]: _c, + }, + [_M], + [0], + + __InvalidGreeting +); +export var OperationWithDefaultsInput = struct( + n1, + _OWDI, + 0, + [_de, _cOD, _tLD, _oTLD], + [() => Defaults, () => ClientOptionalDefaults, 0, 1] +); +export var OperationWithDefaultsOutput = struct( + n1, + _OWDO, + 0, + [ + _dS, + _dB, + _dL, + _dT, + _dBe, + _dBef, + _dSe, + _dI, + _dLe, + _dF, + _dD, + _dM, + _dE, + _dIE, + _eS, + _fB, + _eB, + _zB, + _zS, + _zI, + _zL, + _zF, + _zD, + ], + [0, 2, 64 | 0, 4, 21, 1, 1, 1, 1, 1, 1, 128 | 0, 0, 1, 0, 2, 21, 1, 1, 1, 1, 1, 1] +); +export var RecursiveShapesInputOutput = struct(n1, _RSIO, 0, [_n], [() => RecursiveShapesInputOutputNested1]); +export var RecursiveShapesInputOutputNested1 = struct( + n1, + _RSION, + 0, + [_f, _n], + [0, () => RecursiveShapesInputOutputNested2] +); +export var RecursiveShapesInputOutputNested2 = struct( + n1, + _RSIONe, + 0, + [_b, _rM], + [0, () => RecursiveShapesInputOutputNested1] +); +export var RpcV2CborDenseMapsInputOutput = struct( + n1, + _RVCDMIO, + 0, + [_dSM, _dNM, _dBM, _dSMe, _dSMen], + [() => DenseStructMap, 128 | 1, 128 | 2, 128 | 0, map(n1, _DSMe, 0, 0, 64 | 0)] +); +export var RpcV2CborListInputOutput = struct( + n1, + _RVCLIO, + 0, + [_sL, _sS, _iL, _bL, _tL, _eL, _iEL, _nSL, _sLt, _bLl], + [64 | 0, 64 | 0, 64 | 1, 64 | 2, 64 | 4, 64 | 0, 64 | 1, list(n2, _NSL, 0, 64 | 0), () => StructureList, 64 | 21] +); +export var RpcV2CborSparseMapsInputOutput = struct( + n1, + _RVCSMIO, + 0, + [_sSM, _sNM, _sBM, _sSMp, _sSMpa], + [ + [() => SparseStructMap, 0], + [() => SparseNumberMap, 0], + [() => SparseBooleanMap, 0], + [() => SparseStringMap, 0], + [() => SparseSetMap, 0], + ] +); +export var SimpleScalarStructure = struct( + n1, + _SSS, + 0, + [_tBV, _fBV, _bV, _dV, _fV, _iV, _lV, _sV, _sVt, _bVl], + [2, 2, 1, 1, 1, 1, 1, 1, 0, 21] +); +export var SimpleStructure = struct(n1, _SSi, 0, [_v], [0]); +export var SparseNullsOperationInputOutput = struct( + n1, + _SNOIO, + 0, + [_sSL, _sSMp], + [ + [() => SparseStringList, 0], + [() => SparseStringMap, 0], + ] +); +export var StructureListMember = struct(n1, _SLM, 0, [_a, _b_], [0, 0]); +export var GreetingStruct = struct(n2, _GS, 0, [_h], [0]); +export var RpcV2ProtocolServiceException = error( + "awssdkjs.synthetic.smithy.protocoltests.rpcv2Cbor", + "RpcV2ProtocolServiceException", + 0, + [], + [], + __RpcV2ProtocolServiceException +); +export var ValidationExceptionFieldList = list(n0, _VEFL, 0, () => ValidationExceptionField); +export var StructureList = list(n1, _SLt, 0, () => StructureListMember); +export var TestStringList = 64 | 0; + +export var BlobList = 64 | 21; + +export var BooleanList = 64 | 2; + +export var FooEnumList = 64 | 0; + +export var IntegerEnumList = 64 | 1; + +export var IntegerList = 64 | 1; + +export var NestedStringList = list(n2, _NSL, 0, 64 | 0); +export var SparseStringList = list( + n2, + _SSL, + { + [_s]: 1, + }, + 0 +); +export var StringList = 64 | 0; + +export var StringSet = 64 | 0; + +export var TimestampList = 64 | 4; + +export var DenseBooleanMap = 128 | 2; + +export var DenseNumberMap = 128 | 1; + +export var DenseSetMap = map(n1, _DSMe, 0, 0, 64 | 0); +export var DenseStringMap = 128 | 0; + +export var DenseStructMap = map(n1, _DSMen, 0, 0, () => GreetingStruct); +export var SparseBooleanMap = map( + n1, + _SBM, + { + [_s]: 1, + }, + 0, + 2 +); +export var SparseNumberMap = map( + n1, + _SNM, + { + [_s]: 1, + }, + 0, + 1 +); +export var SparseSetMap = map( + n1, + _SSMp, + { + [_s]: 1, + }, + 0, + 64 | 0 +); +export var SparseStructMap = map( + n1, + _SSMpa, + { + [_s]: 1, + }, + 0, + () => GreetingStruct +); +export var TestStringMap = 128 | 0; + +export var SparseStringMap = map( + n2, + _SSM, + { + [_s]: 1, + }, + 0, + 0 +); +export var EmptyInputOutput = op( + n1, + _EIO, + 0, + () => EmptyStructure, + () => EmptyStructure +); +export var Float16 = op( + n1, + _Fl, + 0, + () => Unit, + () => Float16Output +); +export var FractionalSeconds = op( + n1, + _FS, + 0, + () => Unit, + () => FractionalSecondsOutput +); +export var GreetingWithErrors = op( + n1, + _GWE, + 2, + () => Unit, + () => GreetingWithErrorsOutput +); +export var NoInputOutput = op( + n1, + _NIO, + 0, + () => Unit, + () => Unit +); +export var OperationWithDefaults = op( + n1, + _OWD, + 0, + () => OperationWithDefaultsInput, + () => OperationWithDefaultsOutput +); +export var OptionalInputOutput = op( + n1, + _OIO, + 0, + () => SimpleStructure, + () => SimpleStructure +); +export var RecursiveShapes = op( + n1, + _RS, + 0, + () => RecursiveShapesInputOutput, + () => RecursiveShapesInputOutput +); +export var RpcV2CborDenseMaps = op( + n1, + _RVCDM, + 0, + () => RpcV2CborDenseMapsInputOutput, + () => RpcV2CborDenseMapsInputOutput +); +export var RpcV2CborLists = op( + n1, + _RVCL, + 2, + () => RpcV2CborListInputOutput, + () => RpcV2CborListInputOutput +); +export var RpcV2CborSparseMaps = op( + n1, + _RVCSM, + 0, + () => RpcV2CborSparseMapsInputOutput, + () => RpcV2CborSparseMapsInputOutput +); +export var SimpleScalarProperties = op( + n1, + _SSP, + 0, + () => SimpleScalarStructure, + () => SimpleScalarStructure +); +export var SparseNullsOperation = op( + n1, + _SNO, + 0, + () => SparseNullsOperationInputOutput, + () => SparseNullsOperationInputOutput +); diff --git a/private/smithy-rpcv2-cbor-schema/test/functional/rpcv2cbor.spec.ts b/private/smithy-rpcv2-cbor-schema/test/functional/rpcv2cbor.spec.ts new file mode 100644 index 00000000000..5bcfa791a91 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/test/functional/rpcv2cbor.spec.ts @@ -0,0 +1,3284 @@ +// smithy-typescript generated code +import { RpcV2ProtocolClient } from "../../src/RpcV2ProtocolClient"; +import { EmptyInputOutputCommand } from "../../src/commands/EmptyInputOutputCommand"; +import { Float16Command } from "../../src/commands/Float16Command"; +import { FractionalSecondsCommand } from "../../src/commands/FractionalSecondsCommand"; +import { GreetingWithErrorsCommand } from "../../src/commands/GreetingWithErrorsCommand"; +import { NoInputOutputCommand } from "../../src/commands/NoInputOutputCommand"; +import { OperationWithDefaultsCommand } from "../../src/commands/OperationWithDefaultsCommand"; +import { OptionalInputOutputCommand } from "../../src/commands/OptionalInputOutputCommand"; +import { RecursiveShapesCommand } from "../../src/commands/RecursiveShapesCommand"; +import { RpcV2CborDenseMapsCommand } from "../../src/commands/RpcV2CborDenseMapsCommand"; +import { RpcV2CborListsCommand } from "../../src/commands/RpcV2CborListsCommand"; +import { RpcV2CborSparseMapsCommand } from "../../src/commands/RpcV2CborSparseMapsCommand"; +import { SimpleScalarPropertiesCommand } from "../../src/commands/SimpleScalarPropertiesCommand"; +import { SparseNullsOperationCommand } from "../../src/commands/SparseNullsOperationCommand"; +import { cbor } from "@smithy/core/cbor"; +import { expect, test as it } from "vitest"; +import { HttpHandlerOptions, HeaderBag, Endpoint } from "@smithy/types"; +import { HttpHandler, HttpRequest, HttpResponse } from "@smithy/protocol-http"; +import { Readable } from "stream"; + +/** + * Throws an expected exception that contains the serialized request. + */ +class EXPECTED_REQUEST_SERIALIZATION_ERROR extends Error { + constructor(readonly request: HttpRequest) { + super(); + } +} + +/** + * Throws an EXPECTED_REQUEST_SERIALIZATION_ERROR error before sending a + * request. The thrown exception contains the serialized request. + */ +class RequestSerializationTestHandler implements HttpHandler { + handle(request: HttpRequest, options?: HttpHandlerOptions): Promise<{ response: HttpResponse }> { + return Promise.reject(new EXPECTED_REQUEST_SERIALIZATION_ERROR(request)); + } + updateHttpClientConfig(key: never, value: never): void {} + httpHandlerConfigs() { + return {}; + } +} + +/** + * Returns a resolved Promise of the specified response contents. + */ +class ResponseDeserializationTestHandler implements HttpHandler { + isSuccess: boolean; + code: number; + headers: HeaderBag; + body: string | Uint8Array; + isBase64Body: boolean; + + constructor(isSuccess: boolean, code: number, headers?: HeaderBag, body?: string) { + this.isSuccess = isSuccess; + this.code = code; + if (headers === undefined) { + this.headers = {}; + } else { + this.headers = headers; + } + if (body === undefined) { + body = ""; + } + this.body = body; + this.isBase64Body = String(body).length > 0 && Buffer.from(String(body), "base64").toString("base64") === body; + } + + handle(request: HttpRequest, options?: HttpHandlerOptions): Promise<{ response: HttpResponse }> { + return Promise.resolve({ + response: new HttpResponse({ + statusCode: this.code, + headers: this.headers, + body: this.isBase64Body ? toBytes(this.body as string) : Readable.from([this.body]), + }), + }); + } + + updateHttpClientConfig(key: never, value: never): void {} + + httpHandlerConfigs() { + return {}; + } +} + +interface comparableParts { + [key: string]: string; +} + +/** + * Generates a standard map of un-equal values given input parts. + */ +const compareParts = (expectedParts: comparableParts, generatedParts: comparableParts) => { + const unequalParts: any = {}; + Object.keys(expectedParts).forEach((key) => { + if (generatedParts[key] === undefined) { + unequalParts[key] = { exp: expectedParts[key], gen: undefined }; + } else if (!equivalentContents(expectedParts[key], generatedParts[key])) { + unequalParts[key] = { exp: expectedParts[key], gen: generatedParts[key] }; + } + }); + + Object.keys(generatedParts).forEach((key) => { + if (expectedParts[key] === undefined) { + unequalParts[key] = { exp: undefined, gen: generatedParts[key] }; + } + }); + + if (Object.keys(unequalParts).length !== 0) { + return unequalParts; + } + return undefined; +}; + +/** + * Compares all types for equivalent contents, doing nested + * equality checks based on non-`$metadata` + * properties that have defined values. + */ +const equivalentContents = (expected: any, generated: any): boolean => { + if (typeof (global as any).expect === "function") { + expect(normalizeByteArrayType(generated)).toEqual(normalizeByteArrayType(expected)); + return true; + } + + let localExpected = expected; + + // Short circuit on equality. + if (localExpected == generated) { + return true; + } + + if (typeof expected !== "object") { + return expected === generated; + } + + // If a test fails with an issue in the below 6 lines, it's likely + // due to an issue in the nestedness or existence of the property + // being compared. + delete localExpected["$metadata"]; + delete generated["$metadata"]; + Object.keys(localExpected).forEach((key) => localExpected[key] === undefined && delete localExpected[key]); + Object.keys(generated).forEach((key) => generated[key] === undefined && delete generated[key]); + + const expectedProperties = Object.getOwnPropertyNames(localExpected); + const generatedProperties = Object.getOwnPropertyNames(generated); + + // Short circuit on different property counts. + if (expectedProperties.length != generatedProperties.length) { + return false; + } + + // Compare properties directly. + for (var index = 0; index < expectedProperties.length; index++) { + const propertyName = expectedProperties[index]; + if (!equivalentContents(localExpected[propertyName], generated[propertyName])) { + return false; + } + } + + return true; +}; + +const clientParams = { + region: "us-west-2", + credentials: { accessKeyId: "key", secretAccessKey: "secret" }, + endpoint: () => { + const url = new URL("https://localhost/"); + return Promise.resolve({ + hostname: url.hostname, + protocol: url.protocol, + path: url.pathname, + }) as Promise; + }, +}; + +/** + * A wrapper function that shadows `fail` from jest-jasmine2 + * (jasmine2 was replaced with circus in > v27 as the default test runner) + */ +const fail = (error?: any): never => { + throw new Error(error); +}; + +/** + * Hexadecimal to byteArray. + */ +const toBytes = (hex: string) => { + return Buffer.from(hex, "base64"); +}; + +function normalizeByteArrayType(data: any) { + // normalize float32 errors + if (typeof data === "number") { + const u = new Uint8Array(4); + const dv = new DataView(u.buffer, u.byteOffset, u.byteLength); + dv.setFloat32(0, data); + return dv.getFloat32(0); + } + if (!data || typeof data !== "object") { + return data; + } + if (data instanceof Uint8Array) { + return Uint8Array.from(data); + } + if (data instanceof String || data instanceof Boolean || data instanceof Number) { + return data.valueOf(); + } + const output = {} as any; + for (const key of Object.getOwnPropertyNames(data)) { + output[key] = normalizeByteArrayType(data[key]); + } + return output; +} + +/** + * When Input structure is empty we write CBOR equivalent of {} + */ +it("empty_input:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new EmptyInputOutputCommand({} as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/EmptyInputOutput"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect( + r.headers["x-amz-target"], + `Header key "x-amz-target" should have been undefined in ${JSON.stringify(r.headers)}` + ).toBeUndefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v/8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * When output structure is empty we write CBOR equivalent of {} + */ +it("empty_output:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v/8=` + ), + }); + + const params: any = {}; + const command = new EmptyInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * When output structure is empty the client should accept an empty body + */ +it("empty_output_no_body:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `` + ), + }); + + const params: any = {}; + const command = new EmptyInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Ensures that clients can correctly parse float16 +Inf. + */ +it("RpcV2CborFloat16Inf:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWV2YWx1Zfl8AA==` + ), + }); + + const params: any = {}; + const command = new Float16Command(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + value: Infinity, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse float16 -Inf. + */ +it("RpcV2CborFloat16NegInf:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWV2YWx1Zfn8AA==` + ), + }); + + const params: any = {}; + const command = new Float16Command(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + value: -Infinity, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse float16 NaN with high LSB. + */ +it("RpcV2CborFloat16LSBNaN:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWV2YWx1Zfl8AQ==` + ), + }); + + const params: any = {}; + const command = new Float16Command(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + value: NaN, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse float16 NaN with high MSB. + */ +it("RpcV2CborFloat16MSBNaN:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWV2YWx1Zfl+AA==` + ), + }); + + const params: any = {}; + const command = new Float16Command(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + value: NaN, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse a subnormal float16. + */ +it("RpcV2CborFloat16Subnormal:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWV2YWx1ZfkAUA==` + ), + }); + + const params: any = {}; + const command = new Float16Command(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + value: 4.76837158203125e-6, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensures that clients can correctly parse timestamps with fractional seconds + */ +it("RpcV2CborDateTimeWithFractionalSeconds:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2hkYXRldGltZcH7Qcw32zgPvnf/` + ), + }); + + const params: any = {}; + const command = new FractionalSecondsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + datetime: new Date(9.46845296123e8 * 1000), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Parses simple RpcV2 Cbor errors + */ +it("RpcV2CborInvalidGreetingError:Error:GreetingWithErrors", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + false, + 400, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2ZfX3R5cGV4LnNtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNJbnZhbGlkR3JlZXRpbmdnTWVzc2FnZWJIaf8=` + ), + }); + + const params: any = {}; + const command = new GreetingWithErrorsCommand(params); + + try { + await client.send(command); + } catch (err) { + if (err.name !== "InvalidGreeting") { + console.log(err); + fail(`Expected a InvalidGreeting to be thrown, got ${err.name} instead`); + return; + } + const r: any = err; + expect(r["$metadata"].httpStatusCode).toBe(400); + const paramsToValidate: any = [ + { + message: "Hi", + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); + return; + } + fail("Expected an exception to be thrown from response"); +}); + +/** + * Parses a complex error with no message member + */ +it("RpcV2CborComplexError:Error:GreetingWithErrors", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + false, + 400, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3JoVG9wTGV2ZWxpVG9wIGxldmVsZk5lc3RlZL9jRm9vY2Jhcv//` + ), + }); + + const params: any = {}; + const command = new GreetingWithErrorsCommand(params); + + try { + await client.send(command); + } catch (err) { + if (err.name !== "ComplexError") { + console.log(err); + fail(`Expected a ComplexError to be thrown, got ${err.name} instead`); + return; + } + const r: any = err; + expect(r["$metadata"].httpStatusCode).toBe(400); + const paramsToValidate: any = [ + { + TopLevel: "Top level", + Nested: { + Foo: "bar", + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); + return; + } + fail("Expected an exception to be thrown from response"); +}); + +it("RpcV2CborEmptyComplexError:Error:GreetingWithErrors", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + false, + 400, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2ZfX3R5cGV4K3NtaXRoeS5wcm90b2NvbHRlc3RzLnJwY3YyQ2JvciNDb21wbGV4RXJyb3L/` + ), + }); + + const params: any = {}; + const command = new GreetingWithErrorsCommand(params); + + try { + await client.send(command); + } catch (err) { + if (err.name !== "ComplexError") { + console.log(err); + fail(`Expected a ComplexError to be thrown, got ${err.name} instead`); + return; + } + const r: any = err; + expect(r["$metadata"].httpStatusCode).toBe(400); + return; + } + fail("Expected an exception to be thrown from response"); +}); + +/** + * Body is empty and no Content-Type header if no input + */ +it("no_input:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new NoInputOutputCommand({}); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/NoInputOutput"); + + expect( + r.headers["content-type"], + `Header key "content-type" should have been undefined in ${JSON.stringify(r.headers)}` + ).toBeUndefined(); + expect( + r.headers["x-amz-target"], + `Header key "x-amz-target" should have been undefined in ${JSON.stringify(r.headers)}` + ).toBeUndefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(!r.body || r.body === `{}`).toBeTruthy(); + } +}); + +/** + * A `Content-Type` header should not be set if the response body is empty. + */ +it("no_output:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + }, + `` + ), + }); + + const params: any = {}; + const command = new NoInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Clients should accept a CBOR empty struct if there is no output. + */ +it("NoOutputClientAllowsEmptyCbor:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v/8=` + ), + }); + + const params: any = {}; + const command = new NoInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Clients should accept an empty body if there is no output and + * should not raise an error if the `Content-Type` header is set. + */ +it("NoOutputClientAllowsEmptyBody:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `` + ), + }); + + const params: any = {}; + const command = new NoInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Client populates default values in input. + */ +it.skip("RpcV2CborClientPopulatesDefaultValuesInInput:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OperationWithDefaultsCommand({ + defaults: {} as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2hkZWZhdWx0c79tZGVmYXVsdFN0cmluZ2JoaW5kZWZhdWx0Qm9vbGVhbvVrZGVmYXVsdExpc3Sf/3BkZWZhdWx0VGltZXN0YW1wwQBrZGVmYXVsdEJsb2JDYWJja2RlZmF1bHRCeXRlAWxkZWZhdWx0U2hvcnQBbmRlZmF1bHRJbnRlZ2VyCmtkZWZhdWx0TG9uZxhkbGRlZmF1bHRGbG9hdPo/gAAAbWRlZmF1bHREb3VibGX6P4AAAGpkZWZhdWx0TWFwv/9rZGVmYXVsdEVudW1jRk9PbmRlZmF1bHRJbnRFbnVtAWtlbXB0eVN0cmluZ2BsZmFsc2VCb29sZWFu9GllbXB0eUJsb2JAaHplcm9CeXRlAGl6ZXJvU2hvcnQAa3plcm9JbnRlZ2VyAGh6ZXJvTG9uZwBpemVyb0Zsb2F0+gAAAABqemVyb0RvdWJsZfoAAAAA//8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Client skips top level default values in input. + */ +it.skip("RpcV2CborClientSkipsTopLevelDefaultValuesInInput:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OperationWithDefaultsCommand({} as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v/8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Client uses explicitly provided member values over defaults + */ +it.skip("RpcV2CborClientUsesExplicitlyProvidedMemberValuesOverDefaults:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OperationWithDefaultsCommand({ + defaults: { + defaultString: "bye", + defaultBoolean: true, + defaultList: ["a"], + defaultTimestamp: new Date(1000), + defaultBlob: Uint8Array.from("hi", (c) => c.charCodeAt(0)), + defaultByte: 2, + defaultShort: 2, + defaultInteger: 20, + defaultLong: 200, + defaultFloat: 2.0, + defaultDouble: 2.0, + defaultMap: { + name: "Jack", + } as any, + defaultEnum: "BAR", + defaultIntEnum: 2, + emptyString: "foo", + falseBoolean: true, + emptyBlob: Uint8Array.from("hi", (c) => c.charCodeAt(0)), + zeroByte: 1, + zeroShort: 1, + zeroInteger: 1, + zeroLong: 1, + zeroFloat: 1.0, + zeroDouble: 1.0, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2hkZWZhdWx0c7dtZGVmYXVsdFN0cmluZ2NieWVuZGVmYXVsdEJvb2xlYW71a2RlZmF1bHRMaXN0gWFhcGRlZmF1bHRUaW1lc3RhbXDB+z/wAAAAAAAAa2RlZmF1bHRCbG9iQmhpa2RlZmF1bHRCeXRlAmxkZWZhdWx0U2hvcnQCbmRlZmF1bHRJbnRlZ2VyFGtkZWZhdWx0TG9uZxjIbGRlZmF1bHRGbG9hdPpAAAAAbWRlZmF1bHREb3VibGX7QAAAAAAAAABqZGVmYXVsdE1hcKFkbmFtZWRKYWNra2RlZmF1bHRFbnVtY0JBUm5kZWZhdWx0SW50RW51bQJrZW1wdHlTdHJpbmdjZm9vbGZhbHNlQm9vbGVhbvVpZW1wdHlCbG9iQmhpaHplcm9CeXRlAWl6ZXJvU2hvcnQBa3plcm9JbnRlZ2VyAWh6ZXJvTG9uZwFpemVyb0Zsb2F0+j+AAABqemVyb0RvdWJsZfs/8AAAAAAAAP8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Any time a value is provided for a member in the top level of input, it is used, regardless of if its the default. + */ +it.skip("RpcV2CborClientUsesExplicitlyProvidedValuesInTopLevel:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OperationWithDefaultsCommand({ + topLevelDefault: "hi", + otherTopLevelDefault: 0, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v290b3BMZXZlbERlZmF1bHRiaGl0b3RoZXJUb3BMZXZlbERlZmF1bHQA/w==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Typically, non top-level members would have defaults filled in, but if they have the clientOptional trait, the defaults should be ignored. + */ +it.skip("RpcV2CborClientIgnoresNonTopLevelDefaultsOnMembersWithClientOptional:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OperationWithDefaultsCommand({ + clientOptionalDefaults: {} as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OperationWithDefaults"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v3ZjbGllbnRPcHRpb25hbERlZmF1bHRzoP8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Client populates default values when missing in response. + */ +it.skip("RpcV2CborClientPopulatesDefaultsValuesWhenMissingInResponse:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v/8=` + ), + }); + + const params: any = {}; + const command = new OperationWithDefaultsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + defaultString: "hi", + defaultBoolean: true, + defaultList: [], + defaultTimestamp: new Date(0 * 1000), + defaultBlob: Uint8Array.from("abc", (c) => c.charCodeAt(0)), + defaultByte: 1, + defaultShort: 1, + defaultInteger: 10, + defaultLong: 100, + defaultFloat: 1.0, + defaultDouble: 1.0, + defaultMap: {}, + defaultEnum: "FOO", + defaultIntEnum: 1, + emptyString: "", + falseBoolean: false, + emptyBlob: Uint8Array.from("", (c) => c.charCodeAt(0)), + zeroByte: 0, + zeroShort: 0, + zeroInteger: 0, + zeroLong: 0, + zeroFloat: 0.0, + zeroDouble: 0.0, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Client ignores default values if member values are present in the response. + */ +it.skip("RpcV2CborClientIgnoresDefaultValuesIfMemberValuesArePresentInResponse:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v21kZWZhdWx0U3RyaW5nY2J5ZW5kZWZhdWx0Qm9vbGVhbvRrZGVmYXVsdExpc3SBYWFwZGVmYXVsdFRpbWVzdGFtcMH7QAAAAAAAAABrZGVmYXVsdEJsb2JCaGlrZGVmYXVsdEJ5dGUCbGRlZmF1bHRTaG9ydAJuZGVmYXVsdEludGVnZXIUa2RlZmF1bHRMb25nGMhsZGVmYXVsdEZsb2F0+kAAAABtZGVmYXVsdERvdWJsZftAAAAAAAAAAGpkZWZhdWx0TWFwoWRuYW1lZEphY2trZGVmYXVsdEVudW1jQkFSbmRlZmF1bHRJbnRFbnVtAmtlbXB0eVN0cmluZ2Nmb29sZmFsc2VCb29sZWFu9WllbXB0eUJsb2JCaGloemVyb0J5dGUBaXplcm9TaG9ydAFremVyb0ludGVnZXIBaHplcm9Mb25nAWl6ZXJvRmxvYXT6P4AAAGp6ZXJvRG91Ymxl+z/wAAAAAAAA/w==` + ), + }); + + const params: any = {}; + const command = new OperationWithDefaultsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + defaultString: "bye", + defaultBoolean: false, + defaultList: ["a"], + defaultTimestamp: new Date(2 * 1000), + defaultBlob: Uint8Array.from("hi", (c) => c.charCodeAt(0)), + defaultByte: 2, + defaultShort: 2, + defaultInteger: 20, + defaultLong: 200, + defaultFloat: 2.0, + defaultDouble: 2.0, + defaultMap: { + name: "Jack", + }, + defaultEnum: "BAR", + defaultIntEnum: 2, + emptyString: "foo", + falseBoolean: true, + emptyBlob: Uint8Array.from("hi", (c) => c.charCodeAt(0)), + zeroByte: 1, + zeroShort: 1, + zeroInteger: 1, + zeroLong: 1, + zeroFloat: 1.0, + zeroDouble: 1.0, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * When input is empty we write CBOR equivalent of {} + */ +it("optional_input:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new OptionalInputOutputCommand({} as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/OptionalInputOutput"); + + expect( + r.headers["x-amz-target"], + `Header key "x-amz-target" should have been undefined in ${JSON.stringify(r.headers)}` + ).toBeUndefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v/8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * When output is empty we write CBOR equivalent of {} + */ +it("optional_output:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v/8=` + ), + }); + + const params: any = {}; + const command = new OptionalInputOutputCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Serializes recursive structures + */ +it("RpcV2CborRecursiveShapes:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RecursiveShapesCommand({ + nested: { + foo: "Foo1", + nested: { + bar: "Bar1", + recursiveMember: { + foo: "Foo2", + nested: { + bar: "Bar2", + } as any, + } as any, + } as any, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RecursiveShapes"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes recursive structures + */ +it("RpcV2CborRecursiveShapes:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2ZuZXN0ZWS/Y2Zvb2RGb28xZm5lc3RlZL9jYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyv2Nmb29kRm9vMmZuZXN0ZWS/Y2JhcmRCYXIy//////8=` + ), + }); + + const params: any = {}; + const command = new RecursiveShapesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + nested: { + foo: "Foo1", + nested: { + bar: "Bar1", + recursiveMember: { + foo: "Foo2", + nested: { + bar: "Bar2", + }, + }, + }, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Deserializes recursive structures encoded using a map with definite length + */ +it("RpcV2CborRecursiveShapesUsingDefiniteLength:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWZuZXN0ZWSiY2Zvb2RGb28xZm5lc3RlZKJjYmFyZEJhcjFvcmVjdXJzaXZlTWVtYmVyomNmb29kRm9vMmZuZXN0ZWShY2JhcmRCYXIy` + ), + }); + + const params: any = {}; + const command = new RecursiveShapesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + nested: { + foo: "Foo1", + nested: { + bar: "Bar1", + recursiveMember: { + foo: "Foo2", + nested: { + bar: "Bar2", + }, + }, + }, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes maps + */ +it("RpcV2CborMaps:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborDenseMapsCommand({ + denseStructMap: { + foo: { + hi: "there", + } as any, + baz: { + hi: "bye", + } as any, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Ensure that 0 and false are sent over the wire in all maps and lists + */ +it("RpcV2CborSerializesZeroValuesInMaps:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborDenseMapsCommand({ + denseNumberMap: { + x: 0, + } as any, + denseBooleanMap: { + x: false, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * A request that contains a dense map of sets. + */ +it("RpcV2CborSerializesDenseSetMap:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborDenseMapsCommand({ + denseSetMap: { + x: [], + y: ["a", "b"], + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborDenseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `oWtkZW5zZVNldE1hcKJheIBheYJhYWFi`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Deserializes maps + */ +it("RpcV2CborMaps:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oW5kZW5zZVN0cnVjdE1hcKJjZm9voWJoaWV0aGVyZWNiYXqhYmhpY2J5ZQ==` + ), + }); + + const params: any = {}; + const command = new RpcV2CborDenseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + denseStructMap: { + foo: { + hi: "there", + }, + baz: { + hi: "bye", + }, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensure that 0 and false are sent over the wire in all maps and lists + */ +it("RpcV2CborDeserializesZeroValuesInMaps:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `om5kZW5zZU51bWJlck1hcKFheABvZGVuc2VCb29sZWFuTWFwoWF49A==` + ), + }); + + const params: any = {}; + const command = new RpcV2CborDenseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + denseNumberMap: { + x: 0, + }, + denseBooleanMap: { + x: false, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * A response that contains a dense map of sets + */ +it("RpcV2CborDeserializesDenseSetMap:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWtkZW5zZVNldE1hcKJheIBheYJhYWFi` + ), + }); + + const params: any = {}; + const command = new RpcV2CborDenseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + denseSetMap: { + x: [], + y: ["a", "b"], + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Clients SHOULD tolerate seeing a null value in a dense map, and they SHOULD + * drop the null key-value pair. + */ +it.skip("RpcV2CborDeserializesDenseSetMapAndSkipsNull:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWtkZW5zZVNldE1hcKNheIBheYJhYWFiYXr2` + ), + }); + + const params: any = {}; + const command = new RpcV2CborDenseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + denseSetMap: { + x: [], + y: ["a", "b"], + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes RpcV2 Cbor lists + */ +it("RpcV2CborLists:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborListsCommand({ + stringList: ["foo", "bar"], + stringSet: ["foo", "bar"], + integerList: [1, 2], + booleanList: [true, false], + timestampList: [new Date(1398796238000), new Date(1398796238000)], + enumList: ["Foo", "0"], + intEnumList: [1, 2], + nestedStringList: [ + ["foo", "bar"], + ["baz", "qux"], + ], + structureList: [ + { + a: "1", + b: "2", + } as any, + { + a: "3", + b: "4", + } as any, + ], + blobList: [Uint8Array.from("foo", (c) => c.charCodeAt(0)), Uint8Array.from("bar", (c) => c.charCodeAt(0))], + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2pzdHJpbmdMaXN0gmNmb29jYmFyaXN0cmluZ1NldIJjZm9vY2JhcmtpbnRlZ2VyTGlzdIIBAmtib29sZWFuTGlzdIL19G10aW1lc3RhbXBMaXN0gsH7QdTX+/OAAADB+0HU1/vzgAAAaGVudW1MaXN0gmNGb29hMGtpbnRFbnVtTGlzdIIBAnBuZXN0ZWRTdHJpbmdMaXN0goJjZm9vY2JhcoJjYmF6Y3F1eG1zdHJ1Y3R1cmVMaXN0gqJhYWExYWJhMqJhYWEzYWJhNGhibG9iTGlzdIJDZm9vQ2Jhcv8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes empty JSON lists + */ +it("RpcV2CborListsEmpty:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborListsCommand({ + stringList: [], + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2pzdHJpbmdMaXN0n///`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes empty JSON definite length lists + */ +it("RpcV2CborListsEmptyUsingDefiniteLength:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborListsCommand({ + stringList: [], + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborLists"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `oWpzdHJpbmdMaXN0gA==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes RpcV2 Cbor lists + */ +it("RpcV2CborLists:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2pzdHJpbmdMaXN0n2Nmb29jYmFy/2lzdHJpbmdTZXSfY2Zvb2NiYXL/a2ludGVnZXJMaXN0nwEC/2tib29sZWFuTGlzdJ/19P9tdGltZXN0YW1wTGlzdJ/B+0HU1/vzgAAAwftB1Nf784AAAP9oZW51bUxpc3SfY0Zvb2Ew/2tpbnRFbnVtTGlzdJ8BAv9wbmVzdGVkU3RyaW5nTGlzdJ+fY2Zvb2NiYXL/n2NiYXpjcXV4//9tc3RydWN0dXJlTGlzdJ+/YWFhMWFiYTL/v2FhYTNhYmE0//9oYmxvYkxpc3SfQ2Zvb0NiYXL//w==` + ), + }); + + const params: any = {}; + const command = new RpcV2CborListsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + stringList: ["foo", "bar"], + stringSet: ["foo", "bar"], + integerList: [1, 2], + booleanList: [true, false], + timestampList: [new Date(1398796238 * 1000), new Date(1398796238 * 1000)], + enumList: ["Foo", "0"], + intEnumList: [1, 2], + nestedStringList: [ + ["foo", "bar"], + ["baz", "qux"], + ], + structureList: [ + { + a: "1", + b: "2", + }, + { + a: "3", + b: "4", + }, + ], + blobList: [Uint8Array.from("foo", (c) => c.charCodeAt(0)), Uint8Array.from("bar", (c) => c.charCodeAt(0))], + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes empty RpcV2 Cbor lists + */ +it("RpcV2CborListsEmpty:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2pzdHJpbmdMaXN0n///` + ), + }); + + const params: any = {}; + const command = new RpcV2CborListsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + stringList: [], + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Can deserialize indefinite length text strings inside an indefinite length list + */ +it("RpcV2CborIndefiniteStringInsideIndefiniteListCanDeserialize:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2pzdHJpbmdMaXN0n394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n//8=` + ), + }); + + const params: any = {}; + const command = new RpcV2CborListsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + stringList: [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string", + ], + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Can deserialize indefinite length text strings inside a definite length list + */ +it("RpcV2CborIndefiniteStringInsideDefiniteListCanDeserialize:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `oWpzdHJpbmdMaXN0g394HUFuIGV4YW1wbGUgaW5kZWZpbml0ZSBzdHJpbmcsdyB3aGljaCB3aWxsIGJlIGNodW5rZWQsbiBvbiBlYWNoIGNvbW1h/394NUFub3RoZXIgZXhhbXBsZSBpbmRlZmluaXRlIHN0cmluZyB3aXRoIG9ubHkgb25lIGNodW5r/3ZUaGlzIGlzIGEgcGxhaW4gc3RyaW5n` + ), + }); + + const params: any = {}; + const command = new RpcV2CborListsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + stringList: [ + "An example indefinite string, which will be chunked, on each comma", + "Another example indefinite string with only one chunk", + "This is a plain string", + ], + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes sparse maps + */ +it("RpcV2CborSparseMaps:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborSparseMapsCommand({ + sparseStructMap: { + foo: { + hi: "there", + } as any, + baz: { + hi: "bye", + } as any, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes null map values in sparse maps + */ +it("RpcV2CborSerializesNullMapValues:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborSparseMapsCommand({ + sparseBooleanMap: { + x: null, + } as any, + sparseNumberMap: { + x: null, + } as any, + sparseStringMap: { + x: null, + } as any, + sparseStructMap: { + x: null, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * A request that contains a sparse map of sets + */ +it("RpcV2CborSerializesSparseSetMap:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborSparseMapsCommand({ + sparseSetMap: { + x: [], + y: ["a", "b"], + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL///8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * A request that contains a sparse map of sets. + */ +it("RpcV2CborSerializesSparseSetMapAndRetainsNull:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborSparseMapsCommand({ + sparseSetMap: { + x: [], + y: ["a", "b"], + z: null, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Ensure that 0 and false are sent over the wire in all maps and lists + */ +it("RpcV2CborSerializesZeroValuesInSparseMaps:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new RpcV2CborSparseMapsCommand({ + sparseNumberMap: { + x: 0, + } as any, + sparseBooleanMap: { + x: false, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/RpcV2CborSparseMaps"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Deserializes sparse maps + */ +it("RpcV2CborSparseJsonMaps:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v29zcGFyc2VTdHJ1Y3RNYXC/Y2Zvb79iaGlldGhlcmX/Y2Jher9iaGljYnll////` + ), + }); + + const params: any = {}; + const command = new RpcV2CborSparseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseStructMap: { + foo: { + hi: "there", + }, + baz: { + hi: "bye", + }, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Deserializes null map values + */ +it("RpcV2CborDeserializesNullMapValues:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v3BzcGFyc2VCb29sZWFuTWFwv2F49v9vc3BhcnNlTnVtYmVyTWFwv2F49v9vc3BhcnNlU3RyaW5nTWFwv2F49v9vc3BhcnNlU3RydWN0TWFwv2F49v//` + ), + }); + + const params: any = {}; + const command = new RpcV2CborSparseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseBooleanMap: { + x: null, + }, + sparseNumberMap: { + x: null, + }, + sparseStringMap: { + x: null, + }, + sparseStructMap: { + x: null, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * A response that contains a sparse map of sets + */ +it("RpcV2CborDeserializesSparseSetMap:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2xzcGFyc2VTZXRNYXC/YXmfYWFhYv9heJ////8=` + ), + }); + + const params: any = {}; + const command = new RpcV2CborSparseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseSetMap: { + x: [], + y: ["a", "b"], + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * A response that contains a sparse map of sets with a null + */ +it("RpcV2CborDeserializesSparseSetMapAndRetainsNull:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2xzcGFyc2VTZXRNYXC/YXif/2F5n2FhYWL/YXr2//8=` + ), + }); + + const params: any = {}; + const command = new RpcV2CborSparseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseSetMap: { + x: [], + y: ["a", "b"], + z: null, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Ensure that 0 and false are sent over the wire in all maps and lists + */ +it("RpcV2CborDeserializesZeroValuesInSparseMaps:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v29zcGFyc2VOdW1iZXJNYXC/YXgA/3BzcGFyc2VCb29sZWFuTWFwv2F49P//` + ), + }); + + const params: any = {}; + const command = new RpcV2CborSparseMapsCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseNumberMap: { + x: 0, + }, + sparseBooleanMap: { + x: false, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes simple scalar properties + */ +it("RpcV2CborSimpleScalarProperties:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SimpleScalarPropertiesCommand({ + byteValue: 5, + doubleValue: 1.889, + falseBooleanValue: false, + floatValue: 7.625, + integerValue: 256, + longValue: 9873, + shortValue: 9898, + stringValue: "simple", + trueBooleanValue: true, + blobValue: Uint8Array.from("foo", (c) => c.charCodeAt(0)), + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * RpcV2 Cbor should not serialize null structure values + */ +it("RpcV2CborClientDoesntSerializeNullStructureValues:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SimpleScalarPropertiesCommand({ + stringValue: null, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v/8=`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Supports handling NaN float values. + */ +it("RpcV2CborSupportsNaNFloatInputs:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SimpleScalarPropertiesCommand({ + doubleValue: NaN, + floatValue: NaN, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Supports handling Infinity float values. + */ +it("RpcV2CborSupportsInfinityFloatInputs:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SimpleScalarPropertiesCommand({ + doubleValue: Infinity, + floatValue: Infinity, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Supports handling Infinity float values. + */ +it("RpcV2CborSupportsNegativeInfinityFloatInputs:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SimpleScalarPropertiesCommand({ + doubleValue: -Infinity, + floatValue: -Infinity, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SimpleScalarProperties"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes simple scalar properties + */ +it("RpcV2CborSimpleScalarProperties:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v3B0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb2//` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + trueBooleanValue: true, + falseBooleanValue: false, + byteValue: 5, + doubleValue: 1.889, + floatValue: 7.625, + integerValue: 256, + shortValue: 9898, + stringValue: "simple", + blobValue: Uint8Array.from("foo", (c) => c.charCodeAt(0)), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Deserializes simple scalar properties encoded using a map with definite length + */ +it("RpcV2CborSimpleScalarPropertiesUsingDefiniteLength:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `qXB0cnVlQm9vbGVhblZhbHVl9XFmYWxzZUJvb2xlYW5WYWx1ZfRpYnl0ZVZhbHVlBWtkb3VibGVWYWx1Zfs//jlYEGJN02pmbG9hdFZhbHVl+kD0AABsaW50ZWdlclZhbHVlGQEAanNob3J0VmFsdWUZJqprc3RyaW5nVmFsdWVmc2ltcGxlaWJsb2JWYWx1ZUNmb28=` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + trueBooleanValue: true, + falseBooleanValue: false, + byteValue: 5, + doubleValue: 1.889, + floatValue: 7.625, + integerValue: 256, + shortValue: 9898, + stringValue: "simple", + blobValue: Uint8Array.from("foo", (c) => c.charCodeAt(0)), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * RpcV2 Cbor should not deserialize null structure values + */ +it("RpcV2CborClientDoesntDeserializeNullStructureValues:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2tzdHJpbmdWYWx1Zfb/` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); +}); + +/** + * Supports handling NaN float values. + */ +it("RpcV2CborSupportsNaNFloatOutputs:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2tkb3VibGVWYWx1Zft/+AAAAAAAAGpmbG9hdFZhbHVl+n/AAAD/` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + doubleValue: NaN, + floatValue: NaN, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Supports handling Infinity float values. + */ +it("RpcV2CborSupportsInfinityFloatOutputs:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2tkb3VibGVWYWx1Zft/8AAAAAAAAGpmbG9hdFZhbHVl+n+AAAD/` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + doubleValue: Infinity, + floatValue: Infinity, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Supports handling Negative Infinity float values. + */ +it("RpcV2CborSupportsNegativeInfinityFloatOutputs:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2tkb3VibGVWYWx1Zfv/8AAAAAAAAGpmbG9hdFZhbHVl+v+AAAD/` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + doubleValue: -Infinity, + floatValue: -Infinity, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Supports upcasting from a smaller byte representation of the same data type. + */ +it("RpcV2CborSupportsUpcastingDataOnDeserialize:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2tkb3VibGVWYWx1Zfk+AGpmbG9hdFZhbHVl+UegbGludGVnZXJWYWx1ZRg4aWxvbmdWYWx1ZRkBAGpzaG9ydFZhbHVlCv8=` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + doubleValue: 1.5, + floatValue: 7.625, + integerValue: 56, + longValue: 256, + shortValue: 10, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * The client should skip over additional fields that are not part of the structure. This allows a + * client generated against an older Smithy model to be able to communicate with a server that is + * generated against a newer Smithy model. + */ +it("RpcV2CborExtraFieldsInTheBodyShouldBeSkippedByClients:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v2lieXRlVmFsdWUFa2RvdWJsZVZhbHVl+z/+OVgQYk3TcWZhbHNlQm9vbGVhblZhbHVl9GpmbG9hdFZhbHVl+kD0AABrZXh0cmFPYmplY3S/c2luZGVmaW5pdGVMZW5ndGhNYXC/a3dpdGhBbkFycmF5nwECA///cWRlZmluaXRlTGVuZ3RoTWFwo3J3aXRoQURlZmluaXRlQXJyYXmDAQIDeB1hbmRTb21lSW5kZWZpbml0ZUxlbmd0aFN0cmluZ3gfdGhhdCBoYXMsIGJlZW4gY2h1bmtlZCBvbiBjb21tYWxub3JtYWxTdHJpbmdjZm9vanNob3J0VmFsdWUZJw9uc29tZU90aGVyRmllbGR2dGhpcyBzaG91bGQgYmUgc2tpcHBlZP9saW50ZWdlclZhbHVlGQEAaWxvbmdWYWx1ZRkmkWpzaG9ydFZhbHVlGSaqa3N0cmluZ1ZhbHVlZnNpbXBsZXB0cnVlQm9vbGVhblZhbHVl9WlibG9iVmFsdWVDZm9v/w==` + ), + }); + + const params: any = {}; + const command = new SimpleScalarPropertiesCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + byteValue: 5, + doubleValue: 1.889, + falseBooleanValue: false, + floatValue: 7.625, + integerValue: 256, + longValue: 9873, + shortValue: 9898, + stringValue: "simple", + trueBooleanValue: true, + blobValue: Uint8Array.from("foo", (c) => c.charCodeAt(0)), + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Serializes null values in maps + */ +it("RpcV2CborSparseMapsSerializeNullValues:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SparseNullsOperationCommand({ + sparseStringMap: { + foo: null, + } as any, + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SparseNullsOperation"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Serializes null values in lists + */ +it("RpcV2CborSparseListsSerializeNull:Request", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new RequestSerializationTestHandler(), + }); + + const command = new SparseNullsOperationCommand({ + sparseStringList: [null], + } as any); + try { + await client.send(command); + fail("Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown"); + return; + } catch (err) { + if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) { + fail(err); + return; + } + const r = err.request; + expect(r.method).toBe("POST"); + expect(r.path).toBe("/service/RpcV2Protocol/operation/SparseNullsOperation"); + expect( + r.headers["content-length"], + `Header key "content-length" should have been defined in ${JSON.stringify(r.headers)}` + ).toBeDefined(); + + expect(r.headers["accept"]).toBe("application/cbor"); + expect(r.headers["content-type"]).toBe("application/cbor"); + expect(r.headers["smithy-protocol"]).toBe("rpc-v2-cbor"); + + expect(r.body, `Body was undefined.`).toBeDefined(); + const bodyString = `v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==`; + const unequalParts: any = compareEquivalentCborBodies(bodyString, r.body); + expect(unequalParts).toBeUndefined(); + } +}); + +/** + * Deserializes null values in maps + */ +it("RpcV2CborSparseMapsDeserializeNullValues:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v29zcGFyc2VTdHJpbmdNYXC/Y2Zvb/b//w==` + ), + }); + + const params: any = {}; + const command = new SparseNullsOperationCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseStringMap: { + foo: null, + }, + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +/** + * Deserializes null values in lists + */ +it("RpcV2CborSparseListsDeserializeNull:Response", async () => { + const client = new RpcV2ProtocolClient({ + ...clientParams, + requestHandler: new ResponseDeserializationTestHandler( + true, + 200, + { + "smithy-protocol": "rpc-v2-cbor", + "content-type": "application/cbor", + }, + `v3BzcGFyc2VTdHJpbmdMaXN0n/b//w==` + ), + }); + + const params: any = {}; + const command = new SparseNullsOperationCommand(params); + + let r: any; + try { + r = await client.send(command); + } catch (err) { + fail("Expected a valid response to be returned, got " + err); + return; + } + expect(r["$metadata"].httpStatusCode).toBe(200); + const paramsToValidate: any = [ + { + sparseStringList: [null], + }, + ][0]; + Object.keys(paramsToValidate).forEach((param) => { + expect( + r[param], + `The output field ${param} should have been defined in ${JSON.stringify(r, null, 2)}` + ).toBeDefined(); + expect(equivalentContents(paramsToValidate[param], r[param])).toBe(true); + }); +}); + +const compareEquivalentCborBodies = (expectedBody: string, generatedBody: string | Uint8Array): undefined => { + expect( + normalizeByteArrayType(cbor.deserialize(typeof generatedBody === "string" ? toBytes(generatedBody) : generatedBody)) + ).toEqual(normalizeByteArrayType(cbor.deserialize(toBytes(expectedBody)))); + return undefined; +}; diff --git a/private/smithy-rpcv2-cbor-schema/tsconfig.cjs.json b/private/smithy-rpcv2-cbor-schema/tsconfig.cjs.json new file mode 100644 index 00000000000..9224176da7f --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/tsconfig.cjs.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "outDir": "dist-cjs", + "noCheck": true + } +} diff --git a/private/smithy-rpcv2-cbor-schema/tsconfig.es.json b/private/smithy-rpcv2-cbor-schema/tsconfig.es.json new file mode 100644 index 00000000000..5a76fb65934 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/tsconfig.es.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "lib": ["dom"], + "module": "ESNext", + "moduleResolution": "bundler", + "outDir": "dist-es", + "noCheck": true + } +} diff --git a/private/smithy-rpcv2-cbor-schema/tsconfig.json b/private/smithy-rpcv2-cbor-schema/tsconfig.json new file mode 100644 index 00000000000..956bed461a6 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/node18/tsconfig.json", + "compilerOptions": { + "downlevelIteration": true, + "importHelpers": true, + "incremental": true, + "removeComments": true, + "resolveJsonModule": true, + "rootDir": "src", + "useUnknownInCatchVariables": false + }, + "exclude": ["test/"] +} diff --git a/private/smithy-rpcv2-cbor-schema/tsconfig.types.json b/private/smithy-rpcv2-cbor-schema/tsconfig.types.json new file mode 100644 index 00000000000..b9a5eb78448 --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/tsconfig.types.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "removeComments": false, + "declaration": true, + "declarationDir": "dist-types", + "emitDeclarationOnly": true, + "noCheck": false + }, + "exclude": ["test/**/*", "dist-types/**/*"] +} diff --git a/private/smithy-rpcv2-cbor-schema/vite.config.js b/private/smithy-rpcv2-cbor-schema/vite.config.js new file mode 100644 index 00000000000..e7147d3ac9e --- /dev/null +++ b/private/smithy-rpcv2-cbor-schema/vite.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + test: { + include: ["**/*.spec.ts"], + globals: true, + }, +}); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java index cc6ea0c1f29..e68eb4f942c 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/CommandGenerator.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; @@ -34,6 +35,8 @@ import java.util.function.Function; import java.util.stream.Collectors; import software.amazon.smithy.build.FileManifest; +import software.amazon.smithy.codegen.core.ReservedWords; +import software.amazon.smithy.codegen.core.ReservedWordsBuilder; import software.amazon.smithy.codegen.core.Symbol; import software.amazon.smithy.codegen.core.SymbolProvider; import software.amazon.smithy.model.Model; @@ -57,6 +60,7 @@ import software.amazon.smithy.typescript.codegen.endpointsV2.RuleSetParameterFinder; import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; +import software.amazon.smithy.typescript.codegen.schema.SchemaGenerationAllowlist; import software.amazon.smithy.typescript.codegen.sections.CommandBodyExtraCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandConstructorCodeSection; import software.amazon.smithy.typescript.codegen.sections.CommandPropertiesCodeSection; @@ -74,6 +78,7 @@ final class CommandGenerator implements Runnable { static final String COMMANDS_FOLDER = "commands"; + static final String SCHEMAS_FOLDER = "schemas"; private final TypeScriptSettings settings; private final Model model; @@ -89,6 +94,9 @@ final class CommandGenerator implements Runnable { private final ProtocolGenerator protocolGenerator; private final ApplicationProtocol applicationProtocol; private final SensitiveDataFinder sensitiveDataFinder; + private final ReservedWords reservedWords = new ReservedWordsBuilder() + .loadWords(Objects.requireNonNull(TypeScriptClientCodegenPlugin.class.getResource("reserved-words.txt"))) + .build(); CommandGenerator( TypeScriptSettings settings, @@ -488,7 +496,10 @@ private void generateCommandMiddlewareResolver(String configType) { ); { // Add serialization and deserialization plugin. - writer.write("$T(config, this.serialize, this.deserialize),", serde); + if (!SchemaGenerationAllowlist.allows(service.getId(), settings)) { + writer.write("$T(config, this.serialize, this.deserialize),", serde); + } + // EndpointsV2 writer.addImport( "getEndpointPlugin", @@ -654,10 +665,25 @@ private void addCommandSpecificPlugins() { } } + private void writeSchemaSerde() { + String operationSchema = reservedWords.escape(operation.getId().getName()); + writer.addRelativeImport(operationSchema, null, Paths.get( + ".", CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, "schemas" + )); + writer.write(""" + .sc($L)""", + operationSchema + ); + } + private void writeSerde() { - writer - .write(".ser($L)", getSerdeDispatcher(true)) - .write(".de($L)", getSerdeDispatcher(false)); + if (SchemaGenerationAllowlist.allows(service.getId(), settings)) { + writeSchemaSerde(); + } else { + writer + .write(".ser($L)", getSerdeDispatcher(true)) + .write(".de($L)", getSerdeDispatcher(false)); + } } private String getSerdeDispatcher(boolean isInput) { @@ -665,11 +691,11 @@ private String getSerdeDispatcher(boolean isInput) { return "() => { throw new Error(\"No supported protocol was found\"); }"; } else { String serdeFunctionName = isInput - ? ProtocolGenerator.getSerFunctionShortName(symbol) - : ProtocolGenerator.getDeserFunctionShortName(symbol); + ? ProtocolGenerator.getSerFunctionShortName(symbol) + : ProtocolGenerator.getDeserFunctionShortName(symbol); writer.addRelativeImport(serdeFunctionName, null, - Paths.get(".", CodegenUtils.SOURCE_FOLDER, ProtocolGenerator.PROTOCOLS_FOLDER, - ProtocolGenerator.getSanitizedName(protocolGenerator.getName()))); + Paths.get(".", CodegenUtils.SOURCE_FOLDER, ProtocolGenerator.PROTOCOLS_FOLDER, + ProtocolGenerator.getSanitizedName(protocolGenerator.getName()))); return serdeFunctionName; } } diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java index 71bbc5ad745..1b244298007 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/DirectedTypeScriptCodegen.java @@ -54,6 +54,7 @@ import software.amazon.smithy.typescript.codegen.integration.ProtocolGenerator; import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; +import software.amazon.smithy.typescript.codegen.schema.SchemaGenerator; import software.amazon.smithy.typescript.codegen.validation.LongValidator; import software.amazon.smithy.typescript.codegen.validation.ReplaceLast; import software.amazon.smithy.utils.MapUtils; @@ -111,10 +112,15 @@ public TypeScriptCodegenContext createContext(CreateContextDirective operation.hasTrait(PaginatedTrait.ID))) { PaginationGenerator.writeIndex(model, service, fileManifest); delegator.useFileWriter(PaginationGenerator.PAGINATION_INTERFACE_FILE, paginationWriter -> diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java index 420a52c63c6..235286e5b46 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java @@ -107,10 +107,10 @@ public final class HttpProtocolTestGenerator implements Runnable { private TypeScriptWriter writer; public HttpProtocolTestGenerator( - GenerationContext context, - ProtocolGenerator protocolGenerator, - TestFilter testFilter, - MalformedRequestTestFilter malformedRequestTestFilter + GenerationContext context, + ProtocolGenerator protocolGenerator, + TestFilter testFilter, + MalformedRequestTestFilter malformedRequestTestFilter ) { this.settings = context.getSettings(); this.model = context.getModel(); @@ -165,7 +165,7 @@ private void generateClientOperationTests(OperationShape operation, OperationInd error.getTrait(HttpResponseTestsTrait.class).ifPresent(trait -> { for (HttpResponseTestCase testCase : trait.getTestCasesFor(AppliesTo.CLIENT)) { onlyIfProtocolMatches(testCase, - () -> generateErrorResponseTest(operation, error, testCase)); + () -> generateErrorResponseTest(operation, error, testCase)); } }); } @@ -199,7 +199,7 @@ private void generateServerOperationTests(OperationShape operation, OperationInd error.getTrait(HttpResponseTestsTrait.class).ifPresent(trait -> { for (HttpResponseTestCase testCase : trait.getTestCasesFor(AppliesTo.SERVER)) { onlyIfProtocolMatches(testCase, - () -> generateServerErrorResponseTest(operation, error, testCase)); + () -> generateServerErrorResponseTest(operation, error, testCase)); } }); } @@ -220,7 +220,7 @@ private void onlyIfProtocolMatches(T testCase, R private void onlyIfProtocolMatches(HttpMalformedRequestTestCase testCase, Runnable runnable) { if (testCase.getProtocol().equals(protocol)) { LOGGER.fine(() -> format("Generating malformed request test case for %s.%s", - service.getId(), testCase.getId())); + service.getId(), testCase.getId())); initializeWriterIfNeeded(); runnable.run(); } @@ -241,8 +241,8 @@ private void initializeWriterIfNeeded() { private String createTestCaseFilename() { String baseName = protocol.getName().toLowerCase(Locale.US) - .replace("-", "_") - .replace(".", "_"); + .replace("-", "_") + .replace(".", "_"); return TEST_CASE_FILE_TEMPLATE.replace("%s", baseName); } @@ -254,11 +254,11 @@ private void generateClientRequestTest(OperationShape operation, HttpRequestTest openTestBlock(operation, testCase, testName, () -> { // Create a client with a custom request handler that intercepts requests. writer.openBlock("const client = new $T({", "});\n", serviceSymbol, () -> { - writer.write("...clientParams,"); - testCase.getHost().ifPresent(host -> { - writer.write("endpoint: \"https://$L\",", host); - }); - writer.write("requestHandler: new RequestSerializationTestHandler(),"); + writer.write("...clientParams,"); + testCase.getHost().ifPresent(host -> { + writer.write("endpoint: \"https://$L\",", host); + }); + writer.write("requestHandler: new RequestSerializationTestHandler(),"); }); // Run the parameters through a visitor to adjust for TS specific inputs. @@ -267,27 +267,27 @@ private void generateClientRequestTest(OperationShape operation, HttpRequestTest if (inputOptional.isPresent()) { StructureShape inputShape = model.expectShape(inputOptional.get(), StructureShape.class); writer.write("const command = new $T(", operationSymbol) - .call(() -> params.accept(new CommandInputNodeVisitor(inputShape))) - .write(");"); + .call(() -> params.accept(new CommandInputNodeVisitor(inputShape))) + .write(");"); } else { writer.write("const command = new $T({});", operationSymbol); } // Send the request and look for the expected exception to then perform assertions. writer.write("try {\n" - + " await client.send(command);\n" - + " fail('Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown');\n" - + " return;\n" - + "} catch (err) {\n" - + " if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) {\n" - + " fail(err);\n" - + " return;\n" - + " }\n" - + " const r = err.request;") - .indent() - .call(() -> writeHttpRequestAssertions(testCase)) - .dedent() - .write("}"); + + " await client.send(command);\n" + + " fail('Expected an EXPECTED_REQUEST_SERIALIZATION_ERROR to be thrown');\n" + + " return;\n" + + "} catch (err) {\n" + + " if (!(err instanceof EXPECTED_REQUEST_SERIALIZATION_ERROR)) {\n" + + " fail(err);\n" + + " return;\n" + + " }\n" + + " const r = err.request;") + .indent() + .call(() -> writeHttpRequestAssertions(testCase)) + .dedent() + .write("}"); }); } @@ -296,8 +296,8 @@ private void generateServerRequestTest(OperationShape operation, HttpRequestTest // Lowercase all the headers we're expecting as this is what we'll get. Map headers = testCase.getHeaders().entrySet().stream() - .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) - .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); + .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) + .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); String queryParameters = Node.prettyPrintJson(buildQueryBag(testCase.getQueryParams())); String headerParameters = Node.prettyPrintJson(ObjectNode.fromStringMap(headers)); String body = testCase.getBody().orElse(null); @@ -342,8 +342,8 @@ private void generateMalformedRequestTest(OperationShape operation, HttpMalforme Symbol operationSymbol = symbolProvider.toSymbol(operation); Map requestHeaders = testCase.getRequest().getHeaders().entrySet().stream() - .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) - .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); + .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) + .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); String queryParameters = Node.prettyPrintJson(buildQueryBag(testCase.getRequest().getQueryParams())); String requestHeaderParameters = Node.prettyPrintJson(ObjectNode.fromStringMap(requestHeaders)); String requestBody = testCase.getRequest().getBody().orElse(null); @@ -403,9 +403,9 @@ private void setupStubService(Symbol operationSymbol, // Cast the service as any so TS will ignore the fact that the type being passed in is incomplete. writer.openBlock( - "const handler = $L(testService as $T<{}>, (ctx: {}, failures: __ValidationFailure[]) => {", - "});", getHandlerName, serviceSymbol, - () -> writer.write("if (failures) { throw failures; } return undefined;") + "const handler = $L(testService as $T<{}>, (ctx: {}, failures: __ValidationFailure[]) => {", + "});", getHandlerName, serviceSymbol, + () -> writer.write("if (failures) { throw failures; } return undefined;") ); } else { writer.write("const handler = $L(testService as $T<{}>);", getHandlerName, serviceSymbol); @@ -509,7 +509,7 @@ private void writeHttpQueryAssertions(HttpRequestTestCase testCase) { writer.write("const queryString = buildQueryString(r.query);"); explicitQueryValues.forEach(explicitQueryValue -> - writer.write("expect(queryString).toContain($S);", explicitQueryValue)); + writer.write("expect(queryString).toContain($S);", explicitQueryValue)); } writer.write(""); } @@ -588,8 +588,8 @@ private void writeHttpBodyMessageAssertion(String messageRegex, String mediaType String comparatorInvoke = registerMessageRegexStub(mediaType); writer.writeInline("expect(") - .writeInline(comparatorInvoke, messageRegex) - .write(").toEqual(true);"); + .writeInline(comparatorInvoke, messageRegex) + .write(").toEqual(true);"); } private String registerBodyComparatorStub(String mediaType) { @@ -623,7 +623,7 @@ private String registerBodyComparatorStub(String mediaType) { return "compareEquivalentCborBodies(bodyString, r.body)"; default: LOGGER.warning("Unable to compare bodies with unknown media type `" + mediaType - + "`, defaulting to direct comparison."); + + "`, defaulting to direct comparison."); writer.addImport("Encoder", "__Encoder", TypeScriptDependency.SMITHY_TYPES); additionalStubs.add("protocol-test-unknown-type-stub.ts"); return "compareEquivalentUnknownTypeBodies(utf8Encoder, bodyString, r.body)"; @@ -651,17 +651,17 @@ public void generateServerResponseTest(OperationShape operation, HttpResponseTes Symbol outputType = operationSymbol.expectProperty("outputType", Symbol.class); writer.openBlock("class TestService implements Partial<$T<{}>> {", "}", serviceSymbol, () -> { writer.openBlock("$L(input: any, ctx: {}): Promise<$T> {", "}", - operationSymbol.getName(), outputType, () -> { - Optional outputOptional = operation.getOutput(); - if (outputOptional.isPresent()) { - StructureShape outputShape = model.expectShape(outputOptional.get(), StructureShape.class); - writer.writeInline("let response = "); - testCase.getParams().accept(new CommandInputNodeVisitor(outputShape, true)); - writer.write("return Promise.resolve({ ...response, '$$metadata': {} });"); - } else { - writer.write("return Promise.resolve({ '$$metadata': {} });"); - } - }); + operationSymbol.getName(), outputType, () -> { + Optional outputOptional = operation.getOutput(); + if (outputOptional.isPresent()) { + StructureShape outputShape = model.expectShape(outputOptional.get(), StructureShape.class); + writer.writeInline("let response = "); + testCase.getParams().accept(new CommandInputNodeVisitor(outputShape, true)); + writer.write("return Promise.resolve({ ...response, '$$metadata': {} });"); + } else { + writer.write("return Promise.resolve({ '$$metadata': {} });"); + } + }); }); writeServerResponseTest(operation, testCase); }); @@ -676,19 +676,19 @@ private void generateResponseTest(OperationShape operation, HttpResponseTestCase // Invoke the handler and look for the expected response to then perform assertions. writer.write("let r: any;"); writer.write("try {\n" - + " r = await client.send(command);\n" - + "} catch (err) {\n" - + " fail(\"Expected a valid response to be returned, got \" + err);\n" - + " return;\n" - + "}"); + + " r = await client.send(command);\n" + + "} catch (err) {\n" + + " fail(\"Expected a valid response to be returned, got \" + err);\n" + + " return;\n" + + "}"); writeResponseAssertions(operation, testCase); }); } private void generateServerErrorResponseTest( - OperationShape operation, - StructureShape error, - HttpResponseTestCase testCase + OperationShape operation, + StructureShape error, + HttpResponseTestCase testCase ) { Symbol serviceSymbol = symbolProvider.toSymbol(service); Symbol operationSymbol = symbolProvider.toSymbol(operation); @@ -763,22 +763,22 @@ private void writeServerResponseTest(OperationShape operation, HttpResponseTestC writer.addImport("ServiceException", "__ServiceException", TypeScriptDependency.SERVER_COMMON); writer.addImport("OperationSerializer", "__OperationSerializer", TypeScriptDependency.SERVER_COMMON); writer.openBlock("const serFn: (op: $1T) => __OperationSerializer<$2T<{}>, $1T, __ServiceException> = (op) =>" - + " { return new TestSerializer(); };", serviceOperationsSymbol, serviceSymbol); + + " { return new TestSerializer(); };", serviceOperationsSymbol, serviceSymbol); writer.addRelativeImport("serializeFrameworkException", null, Paths.get(".", CodegenUtils.SOURCE_FOLDER, ProtocolGenerator.PROTOCOLS_FOLDER, ProtocolGenerator.getSanitizedName(protocolGenerator.getName()))); writer.addImport("ValidationFailure", "__ValidationFailure", TypeScriptDependency.SERVER_COMMON); writer.write("const handler = new $T(service, testMux, serFn, serializeFrameworkException, " - + "(ctx: {}, f: __ValidationFailure[]) => { if (f) { throw f; } return undefined;});", handlerSymbol); + + "(ctx: {}, f: __ValidationFailure[]) => { if (f) { throw f; } return undefined;});", handlerSymbol); writer.write("let r = await handler.handle(request, {})").write(""); writeHttpResponseAssertions(testCase); } private void generateErrorResponseTest( - OperationShape operation, - StructureShape error, - HttpResponseTestCase testCase + OperationShape operation, + StructureShape error, + HttpResponseTestCase testCase ) { // Use a compound test_case name so we generate unique tests // for each error on each operation safely. This is useful in validating @@ -791,19 +791,19 @@ private void generateErrorResponseTest( // Invoke the handler and look for the expected exception to then perform assertions. writer.write("try {\n" - + " await client.send(command);\n" - + "} catch (err) {\n" - + " if (err.name !== \"$1L\") {\n" - + " console.log(err);\n" - + " fail(`Expected a $1L to be thrown, got $${err.name} instead`);\n" - + " return;\n" - + " }\n" - + " const r: any = err;", error.getId().getName()) - .indent() - .call(() -> writeResponseAssertions(error, testCase)) - .write("return;") - .dedent() - .write("}"); + + " await client.send(command);\n" + + "} catch (err) {\n" + + " if (err.name !== \"$1L\") {\n" + + " console.log(err);\n" + + " fail(`Expected a $1L to be thrown, got $${err.name} instead`);\n" + + " return;\n" + + " }\n" + + " const r: any = err;", error.getId().getName()) + .indent() + .call(() -> writeResponseAssertions(error, testCase)) + .write("return;") + .dedent() + .write("}"); writer.write("fail('Expected an exception to be thrown from response');"); }); } @@ -813,23 +813,23 @@ private void writeResponseTestSetup(OperationShape operation, HttpResponseTestCa // Lowercase all the headers we're expecting as this is what we'll get. Map headers = testCase.getHeaders().entrySet().stream() - .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) - .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); + .map(entry -> new Pair<>(entry.getKey().toLowerCase(Locale.US), entry.getValue())) + .collect(MapUtils.toUnmodifiableMap(Pair::getLeft, Pair::getRight)); String headerParameters = Node.prettyPrintJson(ObjectNode.fromStringMap(headers)); String body = testCase.getBody().orElse(null); // Create a client with a custom request handler that intercepts requests. writer.openBlock("const client = new $T({", "});\n", serviceSymbol, () -> { - writer.write("...clientParams,"); - writer.openBlock("requestHandler: new ResponseDeserializationTestHandler(", ")", () -> { - writer.write("$L,", isSuccess); - writer.write("$L,", testCase.getCode()); - writer.write("$L,", headers.isEmpty() ? "undefined" : headerParameters); - if (body != null) { - writer.write("`$L`,", body); - } - }); + writer.write("...clientParams,"); + writer.openBlock("requestHandler: new ResponseDeserializationTestHandler(", ")", () -> { + writer.write("$L,", isSuccess); + writer.write("$L,", testCase.getCode()); + writer.write("$L,", headers.isEmpty() ? "undefined" : headerParameters); + if (body != null) { + writer.write("`$L`,", body); + } }); + }); // Set the command's parameters to empty, using the any type to // trick TS in to letting us send this command through. @@ -848,13 +848,13 @@ private void writeRequestParamAssertions(OperationShape operation, HttpRequestTe ObjectNode params = testCase.getParams(); if (!params.isEmpty()) { StructureShape testInputShape = model.expectShape( - operation.getInput().orElseThrow(() -> new CodegenException("Foo")), - StructureShape.class); + operation.getInput().orElseThrow(() -> new CodegenException("Foo")), + StructureShape.class); // Use this trick wrapper to not need more complex trailing comma handling. writer.write("const paramsToValidate: any = [") - .call(() -> params.accept(new CommandOutputNodeVisitor(testInputShape))) - .write("][0];"); + .call(() -> params.accept(new CommandOutputNodeVisitor(testInputShape))) + .write("][0];"); // Extract a payload binding if present. Optional pb = Optional.empty(); @@ -870,7 +870,7 @@ private void writeRequestParamAssertions(OperationShape operation, HttpRequestTe writer.addImport("streamCollector", "__streamCollector", TypeScriptDependency.AWS_SDK_NODE_HTTP_HANDLER); writer.write("const comparableBlob = await __streamCollector(r[$S]);", - payloadBinding.get().getMemberName()); + payloadBinding.get().getMemberName()); }); } } @@ -883,49 +883,49 @@ private void writeResponseParamAssertions(Shape operationOrError, HttpResponseTe testOutputShape = operationOrError.asStructureShape().get(); } else { testOutputShape = model.expectShape( - operationOrError.asOperationShape().get().getOutput() - .orElseThrow(() -> new CodegenException("Foo")), - StructureShape.class); + operationOrError.asOperationShape().get().getOutput() + .orElseThrow(() -> new CodegenException("Foo")), + StructureShape.class); } // Use this trick wrapper to not need more complex trailing comma handling. writer.write("const paramsToValidate: any = [") - .call(() -> params.accept(new CommandOutputNodeVisitor(testOutputShape))) - .write("][0];"); + .call(() -> params.accept(new CommandOutputNodeVisitor(testOutputShape))) + .write("][0];"); // Extract a payload binding if present. Optional payloadBinding = operationOrError.asOperationShape() - .map(operationShape -> { - HttpBindingIndex index = HttpBindingIndex.of(model); - List payloadBindings = index.getResponseBindings(operationOrError, - Location.PAYLOAD); - if (!payloadBindings.isEmpty()) { - return payloadBindings.get(0); - } - return null; - }); + .map(operationShape -> { + HttpBindingIndex index = HttpBindingIndex.of(model); + List payloadBindings = index.getResponseBindings(operationOrError, + Location.PAYLOAD); + if (!payloadBindings.isEmpty()) { + return payloadBindings.get(0); + } + return null; + }); writeParamAssertions(writer, payloadBinding, () -> { writer.write("const comparableBlob = await client.config.streamCollector(r[$S]);", - payloadBinding.get().getMemberName()); + payloadBinding.get().getMemberName()); }); } } private void writeParamAssertions( - TypeScriptWriter writer, - Optional payloadBinding, - Runnable writeComparableBlob + TypeScriptWriter writer, + Optional payloadBinding, + Runnable writeComparableBlob ) { // If we have a streaming payload blob, we need to collect it to something that // can be compared with the test contents. This emulates the customer experience. boolean hasStreamingPayloadBlob = payloadBinding - .map(binding -> - model.getShape(binding.getMember().getTarget()) - .filter(Shape::isBlobShape) - .filter(s -> s.hasTrait(StreamingTrait.ID)) - .isPresent()) - .orElse(false); + .map(binding -> + model.getShape(binding.getMember().getTarget()) + .filter(Shape::isBlobShape) + .filter(s -> s.hasTrait(StreamingTrait.ID)) + .isPresent()) + .orElse(false); if (hasStreamingPayloadBlob) { writeComparableBlob.run(); @@ -940,7 +940,7 @@ private void writeParamAssertions( ).toBeDefined();"""); if (hasStreamingPayloadBlob) { writer.openBlock("if (param === $S) {", "} else {", payloadBinding.get().getMemberName(), () -> - writer.write(""" + writer.write(""" expect(equivalentContents(paramsToValidate[param], \ comparableBlob)).toBe(true); """)); @@ -957,10 +957,10 @@ private void writeParamAssertions( } private void openTestBlock( - OperationShape operation, - HttpMessageTestCase testCase, - String testName, - Runnable f + OperationShape operation, + HttpMessageTestCase testCase, + String testName, + Runnable f ) { // Skipped tests are still generated, just not run. if (testFilter.skip(service, operation, testCase, settings)) { @@ -971,10 +971,10 @@ private void openTestBlock( } private void openTestBlock( - OperationShape operation, - HttpMalformedRequestTestCase testCase, - String testName, - Runnable f + OperationShape operation, + HttpMalformedRequestTestCase testCase, + String testName, + Runnable f ) { // Skipped tests are still generated, just not run. if (malformedRequestTestFilter.skip(service, operation, testCase, settings)) { @@ -1095,7 +1095,7 @@ public Void objectNode(ObjectNode node) { memberShape = wrapperShape.asMapShape().get().getValue(); } else { throw new CodegenException("Unknown shape type for object node when " - + "generating protocol test input: " + wrapperShape.getType()); + + "generating protocol test input: " + wrapperShape.getType()); } // Handle auto-filling idempotency token values to the explicit value. @@ -1149,7 +1149,7 @@ public Void stringNode(StringNode node) { break; default: throw new CodegenException(String.format( - "Unexpected string value for `%s`: \"%s\"", workingShape.getId(), node.getValue())); + "Unexpected string value for `%s`: \"%s\"", workingShape.getId(), node.getValue())); } } else { writer.write("$S,", node.getValue()); @@ -1177,10 +1177,10 @@ public interface TestFilter { * @return True if the test should be skipped, false otherwise. */ boolean skip( - ServiceShape service, - OperationShape operation, - HttpMessageTestCase testCase, - TypeScriptSettings settings + ServiceShape service, + OperationShape operation, + HttpMessageTestCase testCase, + TypeScriptSettings settings ); } @@ -1203,10 +1203,10 @@ public interface MalformedRequestTestFilter { * @return True if the test should be skipped, false otherwise. */ boolean skip( - ServiceShape service, - OperationShape operation, - HttpMalformedRequestTestCase testCase, - TypeScriptSettings settings + ServiceShape service, + OperationShape operation, + HttpMalformedRequestTestCase testCase, + TypeScriptSettings settings ); } @@ -1299,7 +1299,7 @@ public Void objectNode(ObjectNode node) { memberShape = wrapperShape.asMapShape().get().getValue(); } else { throw new CodegenException("Unknown shape type for object node when " - + "generating protocol test output: " + wrapperShape.getType()); + + "generating protocol test output: " + wrapperShape.getType()); } // Handle error standardization to the down-cased "message". @@ -1313,8 +1313,8 @@ public Void objectNode(ObjectNode node) { // Alter valueNode to downcase keys if it's a map for prefixHeaders. // This is an enforced behavior of the fetch handler. Node renderNode = memberShape.hasTrait(HttpPrefixHeadersTrait.class) - ? downcaseNodeKeys(valueNode.expectObjectNode()) - : valueNode; + ? downcaseNodeKeys(valueNode.expectObjectNode()) + : valueNode; writer.call(() -> renderNode.accept(this)); }); this.workingShape = wrapperShape; @@ -1326,7 +1326,7 @@ private ObjectNode downcaseNodeKeys(ObjectNode startingNode) { ObjectNode downcasedNode = Node.objectNode(); for (Map.Entry entry : startingNode.getMembers().entrySet()) { downcasedNode = downcasedNode.withMember(entry.getKey().getValue().toLowerCase(Locale.US), - entry.getValue()); + entry.getValue()); } return downcasedNode; } @@ -1349,7 +1349,7 @@ public Void stringNode(StringNode node) { break; default: throw new CodegenException(String.format( - "Unexpected string value for `%s`: \"%s\"", workingShape.getId(), node.getValue())); + "Unexpected string value for `%s`: \"%s\"", workingShape.getId(), node.getValue())); } } else { writer.write("$S,", node.getValue()); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java index fe2d8b544d0..ca11cc5e69b 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/ServiceBareBonesClientGenerator.java @@ -35,6 +35,7 @@ import software.amazon.smithy.typescript.codegen.endpointsV2.EndpointsV2Generator; import software.amazon.smithy.typescript.codegen.integration.RuntimeClientPlugin; import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; +import software.amazon.smithy.typescript.codegen.schema.SchemaGenerationAllowlist; import software.amazon.smithy.typescript.codegen.sections.ClientBodyExtraCodeSection; import software.amazon.smithy.typescript.codegen.sections.ClientConfigCodeSection; import software.amazon.smithy.typescript.codegen.sections.ClientConstructorCodeSection; @@ -435,6 +436,15 @@ private void generateConstructor() { writer.write("this.config = $L;", generateConfigVariable(configVariable)); + if (SchemaGenerationAllowlist.allows(service.getId(), settings)) { + writer.addImportSubmodule( + "getSchemaSerdePlugin", null, + TypeScriptDependency.SMITHY_CORE, "/schema" + ); + writer.write(""" + this.middlewareStack.use(getSchemaSerdePlugin(this.config));"""); + } + // Add runtime plugins that contain middleware to the middleware stack // of the client. for (RuntimeClientPlugin plugin : runtimePlugins) { diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java index 29601f09e15..1227a0a39b1 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/TypeScriptSettings.java @@ -43,6 +43,7 @@ import software.amazon.smithy.model.traits.DefaultTrait; import software.amazon.smithy.model.traits.RequiredTrait; import software.amazon.smithy.typescript.codegen.protocols.ProtocolPriorityConfig; +import software.amazon.smithy.utils.SmithyInternalApi; import software.amazon.smithy.utils.SmithyUnstableApi; /** @@ -87,6 +88,7 @@ public final class TypeScriptSettings { private boolean useLegacyAuth = false; private boolean generateTypeDoc = false; private ProtocolPriorityConfig protocolPriorityConfig = new ProtocolPriorityConfig(null, null); + private boolean generateSchemas = false; @Deprecated public static TypeScriptSettings from(Model model, ObjectNode config) { @@ -141,6 +143,12 @@ public static TypeScriptSettings from(Model model, ObjectNode config, ArtifactTy settings.readProtocolPriorityConfiguration(config); + // Internal undocumented configuration used to control rollout of schemas. + // `true` will eventually be the only available option, and this should not be set by users. + settings.setGenerateSchemas( + config.getBooleanMemberOrDefault("generateSchemas", false) + ); + return settings; } @@ -220,6 +228,22 @@ public void setPackageVersion(String packageVersion) { this.packageVersion = packageVersion; } + /** + * Internal API, do not use. + */ + @SmithyInternalApi + public void setGenerateSchemas(boolean generateSchemas) { + this.generateSchemas = generateSchemas; + } + + /** + * Internal API, do not use. + */ + @SmithyInternalApi + public boolean generateSchemas() { + return generateSchemas; + } + /** * Gets a chunk of custom properties to merge into the generated * package.json file. diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddClientRuntimeConfig.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddClientRuntimeConfig.java index ed49fdd3bec..b4841914400 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddClientRuntimeConfig.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddClientRuntimeConfig.java @@ -58,82 +58,82 @@ public final class AddClientRuntimeConfig implements TypeScriptIntegration { @Override public void addConfigInterfaceFields( - TypeScriptSettings settings, - Model model, - SymbolProvider symbolProvider, - TypeScriptWriter writer + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + TypeScriptWriter writer ) { writer.addImport("Provider", "__Provider", TypeScriptDependency.SMITHY_TYPES); writer.addImport("Logger", "__Logger", TypeScriptDependency.SMITHY_TYPES); writer.writeDocs("Value for how many times a request will be made at most in case of retry.") - .write("maxAttempts?: number | __Provider;\n"); + .write("maxAttempts?: number | __Provider;\n"); writer.writeDocs(""" Specifies which retry algorithm to use. @see https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-smithy-util-retry/Enum/RETRY_MODES/ """) - .write("retryMode?: string | __Provider;\n"); + .write("retryMode?: string | __Provider;\n"); writer.writeDocs("Optional logger for logging debug/info/warn/error.") - .write("logger?: __Logger;\n"); + .write("logger?: __Logger;\n"); writer.addRelativeImport("RuntimeExtension", null, - Paths.get(".", CodegenUtils.SOURCE_FOLDER, "runtimeExtensions")); + Paths.get(".", CodegenUtils.SOURCE_FOLDER, "runtimeExtensions")); writer.writeDocs("Optional extensions") - .write("extensions?: RuntimeExtension[];\n"); + .write("extensions?: RuntimeExtension[];\n"); } @Override public Map> getRuntimeConfigWriters( - TypeScriptSettings settings, - Model model, - SymbolProvider symbolProvider, - LanguageTarget target + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + LanguageTarget target ) { switch (target) { case SHARED: return MapUtils.of( - "logger", writer -> { - writer.addImport("NoOpLogger", null, TypeScriptDependency.AWS_SMITHY_CLIENT); - writer.write("new NoOpLogger()"); - } + "logger", writer -> { + writer.addImport("NoOpLogger", null, TypeScriptDependency.AWS_SMITHY_CLIENT); + writer.write("new NoOpLogger()"); + } ); case BROWSER: return MapUtils.of( - "maxAttempts", writer -> { - writer.addDependency(TypeScriptDependency.UTIL_RETRY); - writer.addImport("DEFAULT_MAX_ATTEMPTS", null, TypeScriptDependency.UTIL_RETRY); - writer.write("DEFAULT_MAX_ATTEMPTS"); - }, - "retryMode", writer -> { - writer.addDependency(TypeScriptDependency.UTIL_RETRY); - writer.addImport("DEFAULT_RETRY_MODE", null, TypeScriptDependency.UTIL_RETRY); - writer.write( - "(async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE)"); - } + "maxAttempts", writer -> { + writer.addDependency(TypeScriptDependency.UTIL_RETRY); + writer.addImport("DEFAULT_MAX_ATTEMPTS", null, TypeScriptDependency.UTIL_RETRY); + writer.write("DEFAULT_MAX_ATTEMPTS"); + }, + "retryMode", writer -> { + writer.addDependency(TypeScriptDependency.UTIL_RETRY); + writer.addImport("DEFAULT_RETRY_MODE", null, TypeScriptDependency.UTIL_RETRY); + writer.write( + "(async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE)"); + } ); case NODE: return MapUtils.of( - "maxAttempts", writer -> { - writer.addDependency(TypeScriptDependency.NODE_CONFIG_PROVIDER); - writer.addImport("loadConfig", "loadNodeConfig", - TypeScriptDependency.NODE_CONFIG_PROVIDER); - writer.addImport("NODE_MAX_ATTEMPT_CONFIG_OPTIONS", null, - TypeScriptDependency.MIDDLEWARE_RETRY); - writer.write("loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config)"); - }, - "retryMode", writer -> { - writer.addDependency(TypeScriptDependency.NODE_CONFIG_PROVIDER); - writer.addImport("loadConfig", "loadNodeConfig", - TypeScriptDependency.NODE_CONFIG_PROVIDER); - writer.addDependency(TypeScriptDependency.MIDDLEWARE_RETRY); - writer.addImport("NODE_RETRY_MODE_CONFIG_OPTIONS", null, - TypeScriptDependency.MIDDLEWARE_RETRY); - writer.addImport("DEFAULT_RETRY_MODE", null, TypeScriptDependency.UTIL_RETRY); - writer.openBlock("loadNodeConfig({", "}, config)", () -> { - writer.write("...NODE_RETRY_MODE_CONFIG_OPTIONS,"); - writer.write("default: async () => " - + "(await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE,"); - }); - } + "maxAttempts", writer -> { + writer.addDependency(TypeScriptDependency.NODE_CONFIG_PROVIDER); + writer.addImport("loadConfig", "loadNodeConfig", + TypeScriptDependency.NODE_CONFIG_PROVIDER); + writer.addImport("NODE_MAX_ATTEMPT_CONFIG_OPTIONS", null, + TypeScriptDependency.MIDDLEWARE_RETRY); + writer.write("loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config)"); + }, + "retryMode", writer -> { + writer.addDependency(TypeScriptDependency.NODE_CONFIG_PROVIDER); + writer.addImport("loadConfig", "loadNodeConfig", + TypeScriptDependency.NODE_CONFIG_PROVIDER); + writer.addDependency(TypeScriptDependency.MIDDLEWARE_RETRY); + writer.addImport("NODE_RETRY_MODE_CONFIG_OPTIONS", null, + TypeScriptDependency.MIDDLEWARE_RETRY); + writer.addImport("DEFAULT_RETRY_MODE", null, TypeScriptDependency.UTIL_RETRY); + writer.openBlock("loadNodeConfig({", "}, config)", () -> { + writer.write("...NODE_RETRY_MODE_CONFIG_OPTIONS,"); + writer.write("default: async () => " + + "(await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE,"); + }); + } ); default: return Collections.emptyMap(); diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddProtocolConfig.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddProtocolConfig.java new file mode 100644 index 00000000000..9433ef8302d --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/integration/AddProtocolConfig.java @@ -0,0 +1,90 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.integration; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.protocol.traits.Rpcv2CborTrait; +import software.amazon.smithy.typescript.codegen.LanguageTarget; +import software.amazon.smithy.typescript.codegen.TypeScriptDependency; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.schema.SchemaGenerationAllowlist; +import software.amazon.smithy.utils.MapUtils; +import software.amazon.smithy.utils.SmithyInternalApi; + + +/** + * Adds a protocol implementation to the runtime config. + */ +@SmithyInternalApi +public final class AddProtocolConfig implements TypeScriptIntegration { + + @Override + public void addConfigInterfaceFields( + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + TypeScriptWriter writer + ) { + // the {{ protocol?: Protocol }} type field is provided + // by the smithy client config interface. + if (!SchemaGenerationAllowlist.allows(settings.getService(), settings)) { + return; + } + + writer + .addImport("ClientProtocol", null, TypeScriptDependency.SMITHY_TYPES) + .addImport("HttpRequest", null, TypeScriptDependency.SMITHY_TYPES) + .addImport("HttpResponse", null, TypeScriptDependency.SMITHY_TYPES) + .writeDocs(""" + The protocol controlling the message type (e.g. HTTP) and format (e.g. JSON) + may be overridden. A default will always be set by the client. + Available options depend on the service's supported protocols and will not be validated by + the client. + @alpha + """) + .write(""" + protocol?: ClientProtocol; + """); + } + + @Override + public Map> getRuntimeConfigWriters( + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + LanguageTarget target + ) { + if (!SchemaGenerationAllowlist.allows(settings.getService(), settings)) { + return Collections.emptyMap(); + } + + String namespace = settings.getService().getNamespace(); + + switch (target) { + case SHARED: + if (Objects.equals(settings.getProtocol(), Rpcv2CborTrait.ID)) { + return MapUtils.of( + "protocol", writer -> { + writer.addImportSubmodule( + "SmithyRpcV2CborProtocol", null, + TypeScriptDependency.SMITHY_CORE, "/cbor"); + writer.write("new SmithyRpcV2CborProtocol({ defaultNamespace: $S })", namespace); + } + ); + } + case BROWSER: + case NODE: + default: + return Collections.emptyMap(); + } + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerationAllowlist.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerationAllowlist.java new file mode 100644 index 00000000000..7e8b633b21a --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerationAllowlist.java @@ -0,0 +1,39 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.HashSet; +import java.util.Set; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.utils.SmithyInternalApi; + + +/** + * + * Controls rollout of schema generation. + * + */ +@SmithyInternalApi +public abstract class SchemaGenerationAllowlist { + private static final Set ALLOWED = new HashSet<>(); + + static { + ALLOWED.add("smithy.protocoltests.rpcv2Cbor#RpcV2Protocol"); + } + + public static boolean allows(String serviceShapeId, TypeScriptSettings settings) { + return ALLOWED.contains(serviceShapeId) && settings.generateSchemas(); + } + + public static boolean allows(ShapeId serviceShapeId, TypeScriptSettings settings) { + return ALLOWED.contains(serviceShapeId.toString()) && settings.generateSchemas(); + } + + public static void allow(String serviceShapeId) { + ALLOWED.add(serviceShapeId); + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java new file mode 100644 index 00000000000..94194686bf1 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaGenerator.java @@ -0,0 +1,587 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +import software.amazon.smithy.build.FileManifest; +import software.amazon.smithy.codegen.core.ReservedWords; +import software.amazon.smithy.codegen.core.ReservedWordsBuilder; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.TopDownIndex; +import software.amazon.smithy.model.shapes.CollectionShape; +import software.amazon.smithy.model.shapes.MapShape; +import software.amazon.smithy.model.shapes.MemberShape; +import software.amazon.smithy.model.shapes.OperationShape; +import software.amazon.smithy.model.shapes.ServiceShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeType; +import software.amazon.smithy.model.shapes.StructureShape; +import software.amazon.smithy.model.shapes.UnionShape; +import software.amazon.smithy.model.traits.ErrorTrait; +import software.amazon.smithy.model.traits.StreamingTrait; +import software.amazon.smithy.model.traits.TimestampFormatTrait; +import software.amazon.smithy.typescript.codegen.CodegenUtils; +import software.amazon.smithy.typescript.codegen.TypeScriptClientCodegenPlugin; +import software.amazon.smithy.typescript.codegen.TypeScriptDependency; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.util.StringStore; +import software.amazon.smithy.utils.SmithyInternalApi; + +/** + * Generates schema objects used to define shape (de)serialization. + */ +@SmithyInternalApi +public class SchemaGenerator implements Runnable { + public static final String SCHEMAS_FOLDER = "schemas"; + private final SchemaReferenceIndex elision; + private final TypeScriptSettings settings; + private final SymbolProvider symbolProvider; + private final Model model; + private final FileManifest fileManifest; + private final StringStore stringStore = new StringStore(); + private final TypeScriptWriter writer = new TypeScriptWriter(""); + + private final Set loadShapesVisited = new HashSet<>(); + + private final Set structureShapes = new TreeSet<>(); + private final Set collectionShapes = new TreeSet<>(); + private final Set mapShapes = new TreeSet<>(); + private final Set unionShapes = new TreeSet<>(); + private final Set operationShapes = new TreeSet<>(); + private final Set simpleShapes = new TreeSet<>(); + + private final Set existsAsSchema = new HashSet<>(); + private final Set requiresNamingDeconfliction = new HashSet<>(); + + private final ReservedWords reservedWords = new ReservedWordsBuilder() + .loadWords(Objects.requireNonNull(TypeScriptClientCodegenPlugin.class.getResource("reserved-words.txt"))) + .build(); + + public SchemaGenerator(Model model, + FileManifest fileManifest, + TypeScriptSettings settings, SymbolProvider symbolProvider) { + this.model = model; + this.fileManifest = fileManifest; + elision = SchemaReferenceIndex.of(model); + this.settings = settings; + this.symbolProvider = symbolProvider; + writer.write( + """ + /* eslint no-var: 0 */ + """ + ); + } + + /** + * Writes all schemas for the model to a schemas.ts file. + */ + @Override + public void run() { + for (ServiceShape service : model.getServiceShapes()) { + if (!SchemaGenerationAllowlist.allows(service.getId(), settings)) { + return; + } + for (OperationShape operation : TopDownIndex.of(model).getContainedOperations(service)) { + operation.getInput().ifPresent(inputShape -> { + loadShapes(model.expectShape(inputShape)); + }); + operation.getOutput().ifPresent(outputShape -> { + loadShapes(model.expectShape(outputShape)); + }); + operation.getErrors().forEach(error -> { + loadShapes(model.expectShape(error)); + }); + operationShapes.add(operation); + existsAsSchema.add(operation); + } + } + deconflictSchemaVarNames(); + + simpleShapes.forEach(this::writeSimpleSchema); + structureShapes.forEach(this::writeStructureSchema); + writeBaseError(); + collectionShapes.forEach(this::writeListSchema); + mapShapes.forEach(this::writeMapSchema); + unionShapes.forEach(this::writeUnionSchema); + operationShapes.forEach(this::writeOperationSchema); + + String stringVariables = stringStore.flushVariableDeclarationCode(); + fileManifest.writeFile( + Paths.get(CodegenUtils.SOURCE_FOLDER, SCHEMAS_FOLDER, "schemas.ts").toString(), + stringVariables + "\n" + writer + ); + } + + /** + * Identifies repeated strings among the schemas to use in StringStore. + */ + private void loadShapes(Shape shape) { + String absoluteName = shape.getId().toString(); + String name = shape.getId().getName(); + + if (shape.isMemberShape()) { + loadShapes(model.expectShape(shape.asMemberShape().get().getTarget())); + return; + } + + if (loadShapesVisited.contains(absoluteName)) { + return; + } + + if (!elision.isReferenceSchema(shape)) { + stringStore.var(name); + } + loadShapesVisited.add(absoluteName); + + switch (shape.getType()) { + case LIST -> { + collectionShapes.add(shape.asListShape().get()); + existsAsSchema.add(shape); + } + case SET -> { + collectionShapes.add(shape.asSetShape().get()); + existsAsSchema.add(shape); + } + case MAP -> { + mapShapes.add(shape.asMapShape().get()); + existsAsSchema.add(shape); + } + case STRUCTURE -> { + structureShapes.add(shape.asStructureShape().get()); + existsAsSchema.add(shape); + } + case UNION -> { + unionShapes.add(shape.asUnionShape().get()); + existsAsSchema.add(shape); + } + case BYTE, INT_ENUM, SHORT, INTEGER, LONG, FLOAT, DOUBLE, BIG_INTEGER, BIG_DECIMAL, BOOLEAN, STRING, + TIMESTAMP, DOCUMENT, ENUM, BLOB -> { + if (elision.traits.hasSchemaTraits(shape)) { + existsAsSchema.add(shape); + } + simpleShapes.add(shape); + } + default -> { + // ... + } + } + + Set memberTargetShapes = shape.getAllMembers().values().stream() + .map(MemberShape::getTarget) + .map(model::expectShape) + .collect(Collectors.toSet()); + + for (Shape memberTargetShape : memberTargetShapes) { + loadShapes(memberTargetShape); + } + } + + private void deconflictSchemaVarNames() { + Set observedShapeNames = new HashSet<>(); + for (Shape shape : existsAsSchema) { + if (observedShapeNames.contains(shape.getId().getName())) { + requiresNamingDeconfliction.add(shape); + } else { + observedShapeNames.add(shape.getId().getName()); + } + } + } + + /** + * @return variable name of the shape's schema, with deconfliction for multiple namespaces with the same + * unqualified name. + */ + private String getShapeVariableName(Shape shape) { + String symbolName = reservedWords.escape(shape.getId().getName()); + if (requiresNamingDeconfliction.contains(shape)) { + symbolName += "_" + stringStore.var(shape.getId().getNamespace(), "n"); + } + return symbolName; + } + + private void writeSimpleSchema(Shape shape) { + if (elision.traits.hasSchemaTraits(shape)) { + writer.addImportSubmodule("sim", "sim", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.write(""" + export var $L = sim($L, $L, $L,""", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + resolveSimpleSchema(shape) + ); + writeTraits(shape); + writer.write(");"); + } + } + + private void writeStructureSchema(StructureShape shape) { + checkedWriteSchema(shape, () -> { + String symbolName = reservedWords.escape(shape.getId().getName()); + if (shape.hasTrait(ErrorTrait.class)) { + String exceptionCtorSymbolName = "__" + symbolName; + writer.addImportSubmodule("error", "error", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.addRelativeImport( + symbolName, + exceptionCtorSymbolName, + Paths.get("..", "models", "index") + ); + writer.openBlock(""" + export var $L = error($L, $L,""", + "", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> doWithMembers(shape) + ); + writer.writeInline(",$L", exceptionCtorSymbolName); + writer.write(");"); + } else { + writer.addImportSubmodule("struct", "struct", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.openBlock(""" + export var $L = struct($L, $L,""", + ");", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> doWithMembers(shape) + ); + } + }); + } + + private void writeBaseError() { + String serviceName = CodegenUtils.getServiceName(settings, model, symbolProvider); + String serviceExceptionName = CodegenUtils.getServiceExceptionName(serviceName); + String namespace = model.getServiceShapes().stream().findFirst().get().getId().getNamespace(); + + String exceptionCtorSymbolName = "__" + serviceExceptionName; + writer.addImportSubmodule("error", "error", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.addRelativeImport( + serviceExceptionName, + exceptionCtorSymbolName, + Paths.get("..", "models", serviceExceptionName) + ); + writer.write(""" + export var $L = error($S, $S, 0, [], []""", + serviceExceptionName, + "awssdkjs.synthetic." + namespace, + serviceExceptionName + ); + writer.writeInline(",$L", exceptionCtorSymbolName); + writer.write(");"); + } + + private void writeUnionSchema(UnionShape shape) { + checkedWriteSchema(shape, () -> { + writer.addImportSubmodule("struct", "uni", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.openBlock(""" + export var $L = uni($L, $L,""", + ");", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> doWithMembers(shape) + ); + }); + } + + /** + * Handles the member entries for unions/structures. + */ + private void doWithMembers(Shape shape) { + writeTraits(shape); + + writer.write(", [ "); + shape.getAllMembers().forEach((memberName, member) -> { + writer.write("$L,", stringStore.var(memberName)); + }); + writer.write(" ], ["); + shape.getAllMembers().forEach((memberName, member) -> { + String ref = resolveSchema(member); + if (elision.traits.hasSchemaTraits(member)) { + writer.openBlock(""" + [$L,\s""", + "],", + ref, + () -> { + writeTraits(member); + } + ); + } else { + writer.write("$L,", ref); + } + }); + writer.write("]"); + } + + private void writeListSchema(CollectionShape shape) { + checkedWriteSchema(shape, () -> { + writer.addImportSubmodule("list", "list", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.openBlock(""" + export var $L = list($L, $L,""", + ");", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> this.doWithMember( + shape, + shape.getMember() + ) + ); + }); + } + + private void writeMapSchema(MapShape shape) { + checkedWriteSchema(shape, () -> { + writer.addImportSubmodule("map", "map", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.openBlock(""" + export var $L = map($L, $L,""", + ");", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> this.doWithMember( + shape, + shape.getKey(), + shape.getValue() + ) + ); + }); + } + + /** + * Write member schema insertion for lists. + */ + private void doWithMember(Shape shape, MemberShape memberShape) { + writeTraits(shape); + String ref = resolveSchema(memberShape); + if (elision.traits.hasSchemaTraits(memberShape)) { + writer.openBlock( + ", [$L, ", + "]", + ref, + () -> { + writeTraits(memberShape); + } + ); + } else { + writer.write(", $L", ref); + } + } + + /** + * Write member schema insertion for maps. + */ + private void doWithMember(Shape shape, MemberShape keyShape, MemberShape memberShape) { + writeTraits(shape); + String keyRef = resolveSchema(keyShape); + String valueRef = resolveSchema(memberShape); + if (elision.traits.hasSchemaTraits(memberShape) || elision.traits.hasSchemaTraits(keyShape)) { + writer.openBlock( + ", [$L, ", + "]", + keyRef, + () -> { + writeTraits(keyShape); + } + ); + writer.openBlock( + ", [$L, ", + "]", + valueRef, + () -> { + writeTraits(memberShape); + } + ); + } else { + writer.write(", $L, $L", keyRef, valueRef); + } + } + + private void writeOperationSchema(OperationShape shape) { + writer.addImportSubmodule("op", "op", TypeScriptDependency.SMITHY_CORE, "/schema"); + writer.openBlock(""" + export var $L = op($L, $L,""", + ");", + getShapeVariableName(shape), + stringStore.var(shape.getId().getNamespace(), "n"), + stringStore.var(shape.getId().getName()), + () -> { + writeTraits(shape); + writer.write(""" + , () => $L, () => $L""", + getShapeVariableName(model.expectShape(shape.getInputShape())), + getShapeVariableName(model.expectShape(shape.getOutputShape())) + ); + } + ); + } + + private void writeTraits(Shape shape) { + writer.write( + new SchemaTraitWriter(shape, elision, stringStore).toString() + ); + } + + /** + * Checks whether ok to write minimized schema. + */ + private void checkedWriteSchema(Shape shape, Runnable schemaWriteFn) { + if (shape.getId().getNamespace().equals("smithy.api") + && shape.getId().getName().equals("Unit")) { + // special signal value for operation input/output. + writer.write(""" + export var Unit = "unit" as const; + """); + } else if (!elision.isReferenceSchema(shape) && !elision.traits.hasSchemaTraits(shape)) { + String sentinel = this.resolveSchema(shape); + + writer.write( + """ + export var $L = $L; + """, + getShapeVariableName(shape), + sentinel + ); + } else { + schemaWriteFn.run(); + } + } + + /** + * @return generally the symbol name of the target shape, but sometimes a sentinel value for special types like + * blob and timestamp. + */ + private String resolveSchema(Shape shape) { + MemberShape memberShape = null; + if (shape instanceof MemberShape ms) { + memberShape = ms; + shape = model.expectShape(memberShape.getTarget()); + } + + boolean isReference = elision.isReferenceSchema(shape); + boolean hasTraits = elision.traits.hasSchemaTraits(shape); + + if (!hasTraits) { + try { + return resolveSimpleSchema(memberShape != null ? memberShape : shape); + } catch (IllegalArgumentException ignored) { + // + } + } + + return (isReference || hasTraits ? "() => " : "") + getShapeVariableName(shape); + } + + private String resolveSimpleSchema(Shape shape) { + MemberShape memberShape = null; + if (shape instanceof MemberShape ms) { + memberShape = ms; + shape = model.expectShape(memberShape.getTarget()); + } + + ShapeType type = shape.getType(); + + switch (type) { + case BOOLEAN -> { + return "2"; + } + case STRING, ENUM -> { + return "0"; + } + case TIMESTAMP -> { + Optional trait = shape.getTrait(TimestampFormatTrait.class); + if (memberShape != null && memberShape.hasTrait(TimestampFormatTrait.class)) { + trait = memberShape.getTrait(TimestampFormatTrait.class); + } + return trait.map(timestampFormatTrait -> switch (timestampFormatTrait.getValue()) { + case "date-time" -> "5"; + case "http-date" -> "6"; + case "epoch-seconds" -> "7"; + default -> "4"; + }).orElse("4"); + } + case BLOB -> { + if (shape.hasTrait(StreamingTrait.class)) { + return "42"; + } + return "21"; + } + case BYTE, SHORT, INTEGER, INT_ENUM, LONG, FLOAT, DOUBLE -> { + return "1"; + } + case DOCUMENT -> { + return "15"; + } + case BIG_DECIMAL -> { + return "17"; + } + case BIG_INTEGER -> { + return "19"; + } + case LIST, SET, MAP -> { + return resolveSimpleSchemaNestedContainer(shape, writer, stringStore); + } + default -> { + // + } + } + throw new IllegalArgumentException("shape is not simple"); + } + + private String resolveSimpleSchemaNestedContainer(Shape shape, TypeScriptWriter writer, StringStore stringStore) { + Shape contained; + String factory; + String sentinel; + String keyMemberSchema; + switch (shape.getType()) { + case LIST -> { + contained = shape.asListShape().get().getMember(); + factory = "list"; + keyMemberSchema = ""; + sentinel = "64"; + } + case MAP -> { + contained = shape.asMapShape().get().getValue(); + factory = "map"; + keyMemberSchema = this.resolveSimpleSchema(shape.asMapShape().get().getKey()) + ", "; + sentinel = "128"; + } + default -> { + throw new IllegalArgumentException( + "call to resolveSimpleSchemaNestedContainer with incompatible shape type." + ); + } + } + if (contained.isMemberShape()) { + contained = model.expectShape(contained.asMemberShape().get().getTarget()); + } + + if (contained.isListShape()) { + writer.addImportSubmodule(factory, factory, TypeScriptDependency.SMITHY_CORE, "/schema"); + String schemaVarName = stringStore.var(shape.getId().getName()); + return factory + "(" + stringStore.var(shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + + keyMemberSchema + + this.resolveSimpleSchema(contained) + ")"; + } else if (contained.isMapShape()) { + writer.addImportSubmodule(factory, factory, TypeScriptDependency.SMITHY_CORE, "/schema"); + String schemaVarName = stringStore.var(shape.getId().getName()); + return factory + "(" + stringStore.var(shape.getId().getNamespace(), "n") + ", " + schemaVarName + ", 0, " + + keyMemberSchema + + this.resolveSimpleSchema(contained) + ")"; + } else { + return sentinel + "|" + this.resolveSimpleSchema(contained); + } + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaReferenceIndex.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaReferenceIndex.java new file mode 100644 index 00000000000..4262b978a02 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaReferenceIndex.java @@ -0,0 +1,68 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.KnowledgeIndex; +import software.amazon.smithy.model.shapes.CollectionShape; +import software.amazon.smithy.model.shapes.MapShape; +import software.amazon.smithy.model.shapes.MemberShape; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeType; +import software.amazon.smithy.utils.SmithyInternalApi; + +/** + * Can determine whether a Schema can be defined by a sentinel value. + */ +@SmithyInternalApi +final class SchemaReferenceIndex implements KnowledgeIndex { + public final SchemaTraitFilterIndex traits; + private final Model model; + + SchemaReferenceIndex(Model model) { + this.model = model; + traits = SchemaTraitFilterIndex.of(model); + } + + public static SchemaReferenceIndex of(Model model) { + return model.getKnowledge(SchemaReferenceIndex.class, SchemaReferenceIndex::new); + } + + /** + * A reference shape is a function pointer to a shape that doesn't have a constant numeric + * sentinel value. + * Simple non-aggregate types and lists/maps of those types are considered non-reference + * in TypeScript. + * + * @return whether shape is a reference shape. + */ + public boolean isReferenceSchema(Shape shape) { + Shape targetShape = shape; + if (shape instanceof MemberShape member) { + targetShape = model.expectShape(member.getTarget()); + } + ShapeType type = targetShape.getType(); + switch (type) { + case BOOLEAN, STRING, BYTE, DOUBLE, FLOAT, INTEGER, LONG, SHORT, ENUM, INT_ENUM -> { + return false; + } + case TIMESTAMP, BLOB -> { + return false; + } + case LIST, SET, MAP -> { + if (shape instanceof CollectionShape collection) { + return isReferenceSchema(collection.getMember()); + } else if (shape instanceof MapShape map) { + return isReferenceSchema(map.getValue()); + } + return true; + } + default -> { + return true; + } + } + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitExtension.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitExtension.java new file mode 100644 index 00000000000..44235470e6d --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitExtension.java @@ -0,0 +1,39 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.HashMap; +import java.util.Map; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.Trait; + +public final class SchemaTraitExtension { + public static final SchemaTraitExtension INSTANCE = new SchemaTraitExtension(); + + private final Map customization = new HashMap<>(); + + private SchemaTraitExtension() {} + + public void add(ShapeId traitShapeId, TraitRenderer traitRenderer) { + customization.put(traitShapeId, traitRenderer); + } + + public String render(Trait trait) { + return customization.get(trait.toShapeId()).render(trait); + } + + public boolean contains(Trait trait) { + return contains(trait.toShapeId()); + } + + public boolean contains(ShapeId trait) { + return customization.containsKey(trait); + } + + public interface TraitRenderer { + String render(Trait trait); + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitFilterIndex.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitFilterIndex.java new file mode 100644 index 00000000000..9918bfb3742 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitFilterIndex.java @@ -0,0 +1,149 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.knowledge.KnowledgeIndex; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.EndpointTrait; +import software.amazon.smithy.model.traits.ErrorTrait; +import software.amazon.smithy.model.traits.EventHeaderTrait; +import software.amazon.smithy.model.traits.EventPayloadTrait; +import software.amazon.smithy.model.traits.HostLabelTrait; +import software.amazon.smithy.model.traits.HttpErrorTrait; +import software.amazon.smithy.model.traits.HttpHeaderTrait; +import software.amazon.smithy.model.traits.HttpLabelTrait; +import software.amazon.smithy.model.traits.HttpPayloadTrait; +import software.amazon.smithy.model.traits.HttpPrefixHeadersTrait; +import software.amazon.smithy.model.traits.HttpQueryParamsTrait; +import software.amazon.smithy.model.traits.HttpQueryTrait; +import software.amazon.smithy.model.traits.HttpResponseCodeTrait; +import software.amazon.smithy.model.traits.HttpTrait; +import software.amazon.smithy.model.traits.IdempotencyTokenTrait; +import software.amazon.smithy.model.traits.JsonNameTrait; +import software.amazon.smithy.model.traits.MediaTypeTrait; +import software.amazon.smithy.model.traits.ProtocolDefinitionTrait; +import software.amazon.smithy.model.traits.RequiresLengthTrait; +import software.amazon.smithy.model.traits.SensitiveTrait; +import software.amazon.smithy.model.traits.SparseTrait; +import software.amazon.smithy.model.traits.StreamingTrait; +import software.amazon.smithy.model.traits.Trait; +import software.amazon.smithy.model.traits.TraitDefinition; +import software.amazon.smithy.model.traits.XmlAttributeTrait; +import software.amazon.smithy.model.traits.XmlFlattenedTrait; +import software.amazon.smithy.model.traits.XmlNameTrait; +import software.amazon.smithy.model.traits.XmlNamespaceTrait; +import software.amazon.smithy.utils.SetUtils; +import software.amazon.smithy.utils.SmithyInternalApi; + +@SmithyInternalApi +final class SchemaTraitFilterIndex implements KnowledgeIndex { + private final Set includedTraits = new HashSet<>( + SetUtils.of( + SparseTrait.ID, + // excluded by special schema handling. + // TimestampFormatTrait.ID, + SensitiveTrait.ID, + IdempotencyTokenTrait.ID, + JsonNameTrait.ID, + MediaTypeTrait.ID, + XmlAttributeTrait.ID, + XmlFlattenedTrait.ID, + XmlNameTrait.ID, + XmlNamespaceTrait.ID, + EventHeaderTrait.ID, + EventPayloadTrait.ID, + StreamingTrait.ID, + RequiresLengthTrait.ID, + EndpointTrait.ID, + HttpErrorTrait.ID, + HttpHeaderTrait.ID, + HttpQueryTrait.ID, + HttpLabelTrait.ID, + HttpPayloadTrait.ID, + HttpPrefixHeadersTrait.ID, + HttpQueryParamsTrait.ID, + HttpResponseCodeTrait.ID, + HostLabelTrait.ID, + ErrorTrait.ID, + HttpTrait.ID + ) + ); + private final Map cache = new HashMap<>(); + private final Model model; + + SchemaTraitFilterIndex(Model model) { + Set shapesWithTrait = model.getShapesWithTrait(ProtocolDefinitionTrait.class); + for (Shape shape : shapesWithTrait) { + System.out.println("shape having authDef: " + shape.getId().getName()); + shape.getTrait(ProtocolDefinitionTrait.class).ifPresent(protocolDefinitionTrait -> { + protocolDefinitionTrait.getTraits().forEach(traitShapeId -> { + Shape traitShape = model.expectShape(traitShapeId); + TraitDefinition traitDefinition = model.getTraitDefinition(traitShapeId).get(); + System.out.println("\t trait shape: " + traitShapeId.getName()); + }); + }); + } + + this.model = model; + for (Shape shape : model.toSet()) { + cache.put(shape, hasSchemaTraits(shape)); + } + } + + public static SchemaTraitFilterIndex of(Model model) { + return model.getKnowledge(SchemaTraitFilterIndex.class, SchemaTraitFilterIndex::new); + } + + /** + * @param shape - structure or member, usually. + * @return whether it has at least 1 trait that is needed in a schema. + */ + public boolean hasSchemaTraits(Shape shape) { + return hasSchemaTraits(shape, 0); + } + + public boolean hasSchemaTraits(Shape shape, int depth) { + if (cache.containsKey(shape)) { + return cache.get(shape); + } + if (depth > 20) { + return false; + } + boolean hasSchemaTraits = shape.getAllTraits() + .values() + .stream() + .map(Trait::toShapeId) + .anyMatch(this::includeTrait); + + if (hasSchemaTraits) { + cache.put(shape, true); + return true; + } + + boolean membersHaveSchemaTraits = shape.getAllMembers().values().stream() + .anyMatch(ms -> hasSchemaTraits(ms, depth + 1)); + boolean targetHasSchemaTraits = shape.asMemberShape() + .map(ms -> hasSchemaTraits(model.expectShape(ms.getTarget()), depth + 1)) + .orElse(false); + + cache.put(shape, membersHaveSchemaTraits || targetHasSchemaTraits); + return cache.get(shape); + } + + /** + * @param traitShapeId - query. + * @return whether trait should be included in schema generation. + */ + public boolean includeTrait(ShapeId traitShapeId) { + return includedTraits.contains(traitShapeId) || SchemaTraitExtension.INSTANCE.contains(traitShapeId); + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitGenerator.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitGenerator.java new file mode 100644 index 00000000000..ecad74ac3b5 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitGenerator.java @@ -0,0 +1,130 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.Objects; +import java.util.Set; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.AnnotationTrait; +import software.amazon.smithy.model.traits.EndpointTrait; +import software.amazon.smithy.model.traits.ErrorTrait; +import software.amazon.smithy.model.traits.EventHeaderTrait; +import software.amazon.smithy.model.traits.EventPayloadTrait; +import software.amazon.smithy.model.traits.HostLabelTrait; +import software.amazon.smithy.model.traits.HttpErrorTrait; +import software.amazon.smithy.model.traits.HttpHeaderTrait; +import software.amazon.smithy.model.traits.HttpLabelTrait; +import software.amazon.smithy.model.traits.HttpPayloadTrait; +import software.amazon.smithy.model.traits.HttpPrefixHeadersTrait; +import software.amazon.smithy.model.traits.HttpQueryParamsTrait; +import software.amazon.smithy.model.traits.HttpQueryTrait; +import software.amazon.smithy.model.traits.HttpResponseCodeTrait; +import software.amazon.smithy.model.traits.HttpTrait; +import software.amazon.smithy.model.traits.IdempotencyTokenTrait; +import software.amazon.smithy.model.traits.JsonNameTrait; +import software.amazon.smithy.model.traits.MediaTypeTrait; +import software.amazon.smithy.model.traits.RequiresLengthTrait; +import software.amazon.smithy.model.traits.SensitiveTrait; +import software.amazon.smithy.model.traits.SparseTrait; +import software.amazon.smithy.model.traits.StreamingTrait; +import software.amazon.smithy.model.traits.StringTrait; +import software.amazon.smithy.model.traits.TimestampFormatTrait; +import software.amazon.smithy.model.traits.Trait; +import software.amazon.smithy.model.traits.XmlAttributeTrait; +import software.amazon.smithy.model.traits.XmlFlattenedTrait; +import software.amazon.smithy.model.traits.XmlNameTrait; +import software.amazon.smithy.model.traits.XmlNamespaceTrait; +import software.amazon.smithy.typescript.codegen.util.StringStore; +import software.amazon.smithy.utils.SetUtils; +import software.amazon.smithy.utils.SmithyInternalApi; + + +/** + * Creates the string representing a trait's data. + * For presence-based trait, essentially boolean, a 1 or 2 will be used. + */ +@SmithyInternalApi +public class SchemaTraitGenerator { + private static final String ANNOTATION_TRAIT_VALUE = "1"; + private static final Set ANNOTATION_TRAITS = SetUtils.of( + XmlAttributeTrait.ID, + XmlFlattenedTrait.ID, + EventHeaderTrait.ID, + EventPayloadTrait.ID, + StreamingTrait.ID, + RequiresLengthTrait.ID, + HttpLabelTrait.ID, + HttpPayloadTrait.ID, + HttpQueryParamsTrait.ID, + HttpResponseCodeTrait.ID, + HostLabelTrait.ID, + SparseTrait.ID, + SensitiveTrait.ID, + IdempotencyTokenTrait.ID + ); + + /** + * Data traits are traits with one or more fields of data. + * To allow for the possibility of the traits adding new fields, + * the generated schema object MUST be an array with consistent ordering and size + * for the fields' data. + */ + private static final Set DATA_TRAITS = SetUtils.of( + HttpErrorTrait.ID, + HttpTrait.ID, + EndpointTrait.ID, + XmlNamespaceTrait.ID + ); + + private static final Set STRING_TRAITS = SetUtils.of( + TimestampFormatTrait.ID, + JsonNameTrait.ID, + MediaTypeTrait.ID, + XmlNameTrait.ID, + HttpHeaderTrait.ID, + HttpQueryTrait.ID, + HttpPrefixHeadersTrait.ID, + ErrorTrait.ID + ); + + public String serializeTraitData(Trait trait, StringStore stringStore) { + if (trait instanceof TimestampFormatTrait) { + // this is overridden by {@link SchemaGenerator::resolveSchema} + return ""; + } else if (STRING_TRAITS.contains(trait.toShapeId()) && trait instanceof StringTrait strTrait) { + return stringStore.var(strTrait.getValue()); + } else if (ANNOTATION_TRAITS.contains(trait.toShapeId()) && trait instanceof AnnotationTrait) { + return ANNOTATION_TRAIT_VALUE; + } else if (trait instanceof HttpErrorTrait httpError) { + return Objects.toString(httpError.getCode()); + } else if (trait instanceof HttpTrait httpTrait) { + return """ + ["%s", "%s", %s] + """.formatted( + httpTrait.getMethod(), + httpTrait.getUri(), + httpTrait.getCode() + ); + } else if (DATA_TRAITS.contains(trait.toShapeId())) { + if (trait instanceof EndpointTrait endpointTrait) { + return """ + ["%s"] + """.formatted(endpointTrait.getHostPrefix()); + } else if (trait instanceof XmlNamespaceTrait xmlNamespaceTrait) { + return """ + [%s, %s] + """.formatted( + stringStore.var(xmlNamespaceTrait.getPrefix().orElse("")), + stringStore.var(xmlNamespaceTrait.getUri()) + ); + } + } else if (SchemaTraitExtension.INSTANCE.contains(trait)) { + return SchemaTraitExtension.INSTANCE.render(trait); + } + return """ + /* unhandled trait \s""" + "`" + trait.getClass().getSimpleName() + "` */"; + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitWriter.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitWriter.java new file mode 100644 index 00000000000..ee28532a449 --- /dev/null +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/schema/SchemaTraitWriter.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package software.amazon.smithy.typescript.codegen.schema; + +import java.util.List; +import java.util.Objects; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; +import software.amazon.smithy.model.traits.HttpLabelTrait; +import software.amazon.smithy.model.traits.HttpPayloadTrait; +import software.amazon.smithy.model.traits.HttpQueryParamsTrait; +import software.amazon.smithy.model.traits.HttpResponseCodeTrait; +import software.amazon.smithy.model.traits.IdempotencyTokenTrait; +import software.amazon.smithy.model.traits.IdempotentTrait; +import software.amazon.smithy.model.traits.SensitiveTrait; +import software.amazon.smithy.model.traits.Trait; +import software.amazon.smithy.typescript.codegen.util.StringStore; + + +class SchemaTraitWriter { + private final Shape shape; + private final SchemaReferenceIndex elision; + private final StringStore stringStore; + private final StringBuilder buffer = new StringBuilder(); + private final List compressTraits = List.of( + HttpLabelTrait.ID, + IdempotentTrait.ID, + IdempotencyTokenTrait.ID, + SensitiveTrait.ID, + HttpPayloadTrait.ID, + HttpResponseCodeTrait.ID, + HttpQueryParamsTrait.ID + ); + private final SchemaTraitGenerator traitGenerator = new SchemaTraitGenerator(); + + SchemaTraitWriter( + Shape shape, + SchemaReferenceIndex elision, + StringStore stringStore + ) { + this.shape = shape; + this.elision = elision; + this.stringStore = stringStore; + } + + /** + * @return either the numeric bitvector or object representation of + * the traits on the input shape. + */ + @Override + public String toString() { + if (mayUseCompressedTraits()) { + writeTraitsBitVector(); + } else { + writeTraitsObject(); + } + return buffer.toString(); + } + + private boolean mayUseCompressedTraits() { + return shape.getAllTraits() + .values() + .stream() + .map(Trait::toShapeId) + .filter(elision.traits::includeTrait) + .allMatch(compressTraits::contains); + } + + private void writeTraitsBitVector() { + int bits = 0; + for (int i = 0; i < compressTraits.size(); ++i) { + if (shape.hasTrait(compressTraits.get(i))) { + bits |= (1 << i); + } + } + buffer.append(Objects.toString(bits)); + } + + private void writeTraitsObject() { + buffer.append("{\n"); + + shape.getAllTraits().forEach((shapeId, trait) -> { + if (!elision.traits.includeTrait(trait.toShapeId())) { + return; + } + buffer.append(""" + [%s]: %s,""".formatted( + stringStore.var(shapeId.getName()), + traitGenerator.serializeTraitData(trait, stringStore) + ) + ); + }); + + buffer.append("}"); + } +} diff --git a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java index 458f571a76f..55432c8a628 100644 --- a/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java +++ b/smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/util/StringStore.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.function.Function; +import java.util.regex.Pattern; import software.amazon.smithy.utils.SmithyInternalApi; /** @@ -25,6 +26,11 @@ */ @SmithyInternalApi public final class StringStore { + /** + * Words are the component strings found within `camelCaseWords` or `header-dashed-words`. + */ + private static final Pattern FIND_WORDS = Pattern.compile("(x-amz)|(-\\w{3,})|(^[a-z]{3,})|([A-Z][a-z]{2,})"); + // order doesn't matter for this map. private final Map literalToVariable = new HashMap<>(); @@ -34,6 +40,8 @@ public final class StringStore { // controls incremental output. private final Set writelog = new HashSet<>(); + public StringStore() {} + /** * @param literal - a literal string value. * @return the variable name assigned for that string, which may have been encountered before. @@ -43,6 +51,24 @@ public String var(String literal) { return literalToVariable.computeIfAbsent(literal, this::assignKey); } + /** + * @param literal - a literal string value. + * @param preferredPrefix - a preferred rather than derived variable name. + * @return allocates the variable with the preferred prefix. + */ + public String var(String literal, String preferredPrefix) { + Objects.requireNonNull(literal); + return literalToVariable.computeIfAbsent(literal, (String key) -> assignPreferredKey(key, preferredPrefix)); + } + + /** + * @param literal - query. + * @return whether the literal has already been assigned. + */ + public boolean hasVar(String literal) { + return literalToVariable.containsKey(literal); + } + /** * Outputs the generated code for any constants that have been * allocated but not yet retrieved. @@ -51,13 +77,12 @@ public String flushVariableDeclarationCode() { StringBuilder sourceCode = new StringBuilder(); for (Map.Entry entry : variableToLiteral.entrySet()) { - String v = entry.getKey(); - String l = entry.getValue(); - if (writelog.add(v)) { - sourceCode.append(String.format("const %s = \"%s\";%n", v, l)); + String variable = entry.getKey(); + String literal = entry.getValue(); + if (writelog.add(variable)) { + sourceCode.append(String.format("const %s = \"%s\";%n", variable, literal)); } } - return sourceCode.toString(); } @@ -73,6 +98,20 @@ private String assignKey(String literal) { return variable; } + /** + * Allocates a variable name for a given string literal. + */ + private String assignPreferredKey(String literal, String preferredPrefix) { + int numericSuffix = 0; + String candidate = preferredPrefix + numericSuffix; + while (variableToLiteral.containsKey(candidate)) { + numericSuffix += 1; + candidate = preferredPrefix + numericSuffix; + } + variableToLiteral.put(candidate, literal); + return candidate; + } + /** * Assigns a unique variable using the letters from the literal. * Prefers the uppercase or word-starting letters. diff --git a/smithy-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration b/smithy-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration index a00867554a6..ba1af5a1af0 100644 --- a/smithy-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration +++ b/smithy-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration @@ -1,6 +1,7 @@ software.amazon.smithy.typescript.codegen.endpointsV2.AddDefaultEndpointRuleSet software.amazon.smithy.typescript.codegen.integration.AddBuiltinPlugins software.amazon.smithy.typescript.codegen.integration.AddClientRuntimeConfig +software.amazon.smithy.typescript.codegen.integration.AddProtocolConfig software.amazon.smithy.typescript.codegen.integration.AddEventStreamDependency software.amazon.smithy.typescript.codegen.integration.AddChecksumRequiredDependency software.amazon.smithy.typescript.codegen.integration.AddDefaultsModeDependency diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/CommandGeneratorTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/CommandGeneratorTest.java index 5872dd5ffde..d368c0fffff 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/CommandGeneratorTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/CommandGeneratorTest.java @@ -3,6 +3,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import software.amazon.smithy.build.MockManifest; import software.amazon.smithy.build.PluginContext; @@ -18,6 +19,9 @@ public void addsCommandSpecificPlugins() { ); } + /** + * todo(schema) remove when switched over. + */ @Test public void writesSerializer() { testCommandCodegen( @@ -26,6 +30,9 @@ public void writesSerializer() { ); } + /** + * todo(schema) remove when switched over. + */ @Test public void writesDeserializer() { testCommandCodegen( @@ -34,6 +41,18 @@ public void writesDeserializer() { ); } + /** + * todo(schema) enable when switched over. + */ + @Disabled + @Test + public void writesOperationSchemaRef() { + testCommandCodegen( + "output-structure.smithy", + new String[] {".sc("} + ); + } + @Test public void writesOperationContextParamValues() { testCommandCodegen( diff --git a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/util/StringStoreTest.java b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/util/StringStoreTest.java index dd0339a24ee..bcacbf659d3 100644 --- a/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/util/StringStoreTest.java +++ b/smithy-typescript-codegen/src/test/java/software/amazon/smithy/typescript/codegen/util/StringStoreTest.java @@ -1,7 +1,6 @@ package software.amazon.smithy.typescript.codegen.util; import org.junit.jupiter.api.Test; - import java.util.Objects; import static org.junit.jupiter.api.Assertions.*; diff --git a/smithy-typescript-protocol-test-codegen/smithy-build.json b/smithy-typescript-protocol-test-codegen/smithy-build.json index c9f2c67b36b..7d3a86c1dd2 100644 --- a/smithy-typescript-protocol-test-codegen/smithy-build.json +++ b/smithy-typescript-protocol-test-codegen/smithy-build.json @@ -24,8 +24,34 @@ }, "license": "Apache-2.0" }, + "private": true + } + } + }, + "smithy-rpcv2-cbor-schema": { + "transforms": [ + { + "name": "includeServices", + "args": { + "services": ["smithy.protocoltests.rpcv2Cbor#RpcV2Protocol"] + } + } + ], + "plugins": { + "typescript-codegen": { + "package": "@smithy/smithy-rpcv2-cbor-schema", + "packageVersion": "1.0.0-alpha.1", + "packageJson": { + "author": { + "name": "Smithy team", + "url": "https://smithy.io/" + }, + "scripts": { + }, + "license": "Apache-2.0" + }, "private": true, - "experimentalIdentityAndAuth": false + "generateSchemas": true } } } diff --git a/yarn.lock b/yarn.lock index 6a1afc68a7b..b70d082f566 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2998,6 +2998,49 @@ __metadata: languageName: unknown linkType: soft +"@smithy/smithy-rpcv2-cbor-schema@workspace:private/smithy-rpcv2-cbor-schema": + version: 0.0.0-use.local + resolution: "@smithy/smithy-rpcv2-cbor-schema@workspace:private/smithy-rpcv2-cbor-schema" + dependencies: + "@aws-crypto/sha256-browser": "npm:5.2.0" + "@aws-crypto/sha256-js": "npm:5.2.0" + "@aws-sdk/types": "npm:latest" + "@smithy/config-resolver": "workspace:^" + "@smithy/core": "workspace:^" + "@smithy/fetch-http-handler": "workspace:^" + "@smithy/hash-node": "workspace:^" + "@smithy/invalid-dependency": "workspace:^" + "@smithy/middleware-content-length": "workspace:^" + "@smithy/middleware-endpoint": "workspace:^" + "@smithy/middleware-retry": "workspace:^" + "@smithy/middleware-serde": "workspace:^" + "@smithy/middleware-stack": "workspace:^" + "@smithy/node-config-provider": "workspace:^" + "@smithy/node-http-handler": "workspace:^" + "@smithy/protocol-http": "workspace:^" + "@smithy/smithy-client": "workspace:^" + "@smithy/types": "workspace:^" + "@smithy/url-parser": "workspace:^" + "@smithy/util-base64": "workspace:^" + "@smithy/util-body-length-browser": "workspace:^" + "@smithy/util-body-length-node": "workspace:^" + "@smithy/util-defaults-mode-browser": "workspace:^" + "@smithy/util-defaults-mode-node": "workspace:^" + "@smithy/util-endpoints": "workspace:^" + "@smithy/util-middleware": "workspace:^" + "@smithy/util-retry": "workspace:^" + "@smithy/util-utf8": "workspace:^" + "@tsconfig/node18": "npm:18.2.4" + "@types/node": "npm:^18.19.69" + concurrently: "npm:7.0.0" + downlevel-dts: "npm:0.10.1" + rimraf: "npm:^3.0.0" + tslib: "npm:^2.6.2" + typescript: "npm:~5.8.3" + vitest: "npm:2.1.8" + languageName: unknown + linkType: soft + "@smithy/smithy-rpcv2-cbor@workspace:private/smithy-rpcv2-cbor": version: 0.0.0-use.local resolution: "@smithy/smithy-rpcv2-cbor@workspace:private/smithy-rpcv2-cbor"