diff --git a/.changeset/weak-poems-tease.md b/.changeset/weak-poems-tease.md new file mode 100644 index 00000000000..5c7d557b52f --- /dev/null +++ b/.changeset/weak-poems-tease.md @@ -0,0 +1,14 @@ +--- +"@smithy/eventstream-serde-config-resolver": minor +"@smithy/middleware-apply-body-checksum": minor +"@smithy/middleware-compression": minor +"@smithy/middleware-endpoint": minor +"@smithy/middleware-retry": minor +"@smithy/config-resolver": minor +"@smithy/protocol-http": minor +"@smithy/smithy-client": minor +"@smithy/util-stream": minor +"@smithy/types": minor +--- + +enforce singular config object during client instantiation diff --git a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts index 5a0d9e2af9a..2b1479dbab7 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.spec.ts @@ -20,7 +20,7 @@ describe(resolveCustomEndpointsConfig.name, () => { beforeEach(() => { vi.mocked(normalizeProvider).mockImplementation((input) => - typeof input === "function" ? input : () => Promise.resolve(input) + typeof input === "function" ? (input as any) : () => Promise.resolve(input) ); }); @@ -28,6 +28,11 @@ describe(resolveCustomEndpointsConfig.name, () => { vi.clearAllMocks(); }); + it("maintains object custody", () => { + const input = { ...mockInput }; + expect(resolveCustomEndpointsConfig(input)).toBe(input); + }); + describe("tls", () => { afterEach(() => { expect(normalizeProvider).toHaveBeenCalledTimes(2); @@ -44,7 +49,7 @@ describe(resolveCustomEndpointsConfig.name, () => { }); it("returns true for isCustomEndpoint", () => { - expect(resolveCustomEndpointsConfig(mockInput).isCustomEndpoint).toStrictEqual(true); + expect(resolveCustomEndpointsConfig({ ...mockInput }).isCustomEndpoint).toStrictEqual(true); }); it("returns false when useDualstackEndpoint is not defined", async () => { @@ -56,23 +61,25 @@ describe(resolveCustomEndpointsConfig.name, () => { }); describe("returns normalized endpoint", () => { - afterEach(() => { - expect(normalizeProvider).toHaveBeenCalledTimes(2); - expect(normalizeProvider).toHaveBeenNthCalledWith(1, mockInput.endpoint); - expect(normalizeProvider).toHaveBeenNthCalledWith(2, mockInput.useDualstackEndpoint); - }); - it("calls urlParser endpoint is of type string", async () => { const mockEndpointString = "http://localhost/"; const endpoint = await resolveCustomEndpointsConfig({ ...mockInput, endpoint: mockEndpointString }).endpoint(); expect(endpoint).toStrictEqual(mockEndpoint); expect(mockInput.urlParser).toHaveBeenCalledWith(mockEndpointString); + + expect(normalizeProvider).toHaveBeenCalledTimes(2); + expect(normalizeProvider).toHaveBeenNthCalledWith(1, mockInput.endpoint); + expect(normalizeProvider).toHaveBeenNthCalledWith(2, mockInput.useDualstackEndpoint); }); it("passes endpoint to normalize if not string", async () => { - const endpoint = await resolveCustomEndpointsConfig(mockInput).endpoint(); + const endpoint = await resolveCustomEndpointsConfig({ ...mockInput }).endpoint(); expect(endpoint).toStrictEqual(mockEndpoint); expect(mockInput.urlParser).not.toHaveBeenCalled(); + + expect(normalizeProvider).toHaveBeenCalledTimes(2); + expect(normalizeProvider).toHaveBeenNthCalledWith(1, mockInput.endpoint); + expect(normalizeProvider).toHaveBeenNthCalledWith(2, mockInput.useDualstackEndpoint); }); }); }); diff --git a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.ts b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.ts index eb0e4ed4ebe..a0c639eb6bb 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveCustomEndpointsConfig.ts @@ -37,12 +37,11 @@ export interface CustomEndpointsResolvedConfig extends EndpointsResolvedConfig { export const resolveCustomEndpointsConfig = ( input: T & CustomEndpointsInputConfig & PreviouslyResolved ): T & CustomEndpointsResolvedConfig => { - const { endpoint, urlParser } = input; - return { - ...input, - tls: input.tls ?? true, + const { tls, endpoint, urlParser, useDualstackEndpoint } = input; + return Object.assign(input, { + tls: tls ?? true, endpoint: normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint), isCustomEndpoint: true, - useDualstackEndpoint: normalizeProvider(input.useDualstackEndpoint ?? false), - }; + useDualstackEndpoint: normalizeProvider(useDualstackEndpoint ?? false), + } as CustomEndpointsResolvedConfig); }; diff --git a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts index a13580ae8bd..6653c16a5f5 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.spec.ts @@ -25,7 +25,7 @@ describe(resolveEndpointsConfig.name, () => { beforeEach(() => { vi.mocked(getEndpointFromRegion).mockResolvedValueOnce(mockEndpoint); vi.mocked(normalizeProvider).mockImplementation((input) => - typeof input === "function" ? input : () => Promise.resolve(input) + typeof input === "function" ? (input as any) : () => Promise.resolve(input) ); }); @@ -33,6 +33,11 @@ describe(resolveEndpointsConfig.name, () => { vi.clearAllMocks(); }); + it("maintains object custody", () => { + const input = { ...mockInput }; + expect(resolveEndpointsConfig(input)).toBe(input); + }); + describe("tls", () => { afterEach(() => { expect(normalizeProvider).toHaveBeenNthCalledWith(1, mockInput.useDualstackEndpoint); @@ -53,7 +58,7 @@ describe(resolveEndpointsConfig.name, () => { }); it("returns true when endpoint is defined", () => { - expect(resolveEndpointsConfig(mockInput).isCustomEndpoint).toStrictEqual(true); + expect(resolveEndpointsConfig({ ...mockInput }).isCustomEndpoint).toStrictEqual(true); }); it("returns false when endpoint is not defined", () => { @@ -90,7 +95,7 @@ describe(resolveEndpointsConfig.name, () => { }); it("passes endpoint to normalize if not string", async () => { - const endpoint = await resolveEndpointsConfig(mockInput).endpoint(); + const endpoint = await resolveEndpointsConfig({ ...mockInput }).endpoint(); expect(endpoint).toStrictEqual(mockEndpoint); expect(mockInput.urlParser).not.toHaveBeenCalled(); }); diff --git a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.ts b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.ts index 8a8a810d2d0..f08ebefca8d 100644 --- a/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.ts +++ b/packages/config-resolver/src/endpointsConfig/resolveEndpointsConfig.ts @@ -65,14 +65,13 @@ export const resolveEndpointsConfig = ( input: T & EndpointsInputConfig & PreviouslyResolved ): T & EndpointsResolvedConfig => { const useDualstackEndpoint = normalizeProvider(input.useDualstackEndpoint ?? false); - const { endpoint, useFipsEndpoint, urlParser } = input; - return { - ...input, - tls: input.tls ?? true, + const { endpoint, useFipsEndpoint, urlParser, tls } = input; + return Object.assign(input, { + tls: tls ?? true, endpoint: endpoint ? normalizeProvider(typeof endpoint === "string" ? urlParser(endpoint) : endpoint) : () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }), isCustomEndpoint: !!endpoint, useDualstackEndpoint, - }; + }); }; diff --git a/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts b/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts index c788007dbf6..6b8ce06efc5 100644 --- a/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts +++ b/packages/config-resolver/src/regionConfig/resolveRegionConfig.spec.ts @@ -21,6 +21,13 @@ describe("RegionConfig", () => { vi.clearAllMocks(); }); + it("maintains object custody", () => { + const input = { + region: "us-east-1", + }; + expect(resolveRegionConfig(input)).toBe(input); + }); + describe("region", () => { it("return normalized value with real region if passed as a string", async () => { const resolvedRegionConfig = resolveRegionConfig({ region: mockRegion, useFipsEndpoint: mockUseFipsEndpoint }); diff --git a/packages/config-resolver/src/regionConfig/resolveRegionConfig.ts b/packages/config-resolver/src/regionConfig/resolveRegionConfig.ts index b0e2289984e..86b18771c93 100644 --- a/packages/config-resolver/src/regionConfig/resolveRegionConfig.ts +++ b/packages/config-resolver/src/regionConfig/resolveRegionConfig.ts @@ -45,8 +45,7 @@ export const resolveRegionConfig = (input: T & RegionInputConfig & Previously throw new Error("Region is missing"); } - return { - ...input, + return Object.assign(input, { region: async () => { if (typeof region === "string") { return getRealRegion(region); @@ -61,5 +60,5 @@ export const resolveRegionConfig = (input: T & RegionInputConfig & Previously } return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint(); }, - }; + }); }; diff --git a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts index bb2ec2bf78e..c09b22e06e0 100644 --- a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts +++ b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.spec.ts @@ -9,6 +9,13 @@ describe("resolveEventStreamSerdeConfig", () => { vi.clearAllMocks(); }); + it("maintains object custody", () => { + const input = { + eventStreamSerdeProvider: vi.fn(), + }; + expect(resolveEventStreamSerdeConfig(input)).toBe(input); + }); + it("sets value returned by eventStreamSerdeProvider", () => { const mockReturn = "mockReturn"; eventStreamSerdeProvider.mockReturnValueOnce(mockReturn); diff --git a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.ts b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.ts index 9510dac9dcd..e96f296d43e 100644 --- a/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.ts +++ b/packages/eventstream-serde-config-resolver/src/EventStreamSerdeConfig.ts @@ -28,7 +28,7 @@ interface PreviouslyResolved { */ export const resolveEventStreamSerdeConfig = ( input: T & PreviouslyResolved & EventStreamSerdeInputConfig -): T & EventStreamSerdeResolvedConfig => ({ - ...input, - eventStreamMarshaller: input.eventStreamSerdeProvider(input), -}); +): T & EventStreamSerdeResolvedConfig => + Object.assign(input, { + eventStreamMarshaller: input.eventStreamSerdeProvider(input), + }); diff --git a/packages/middleware-apply-body-checksum/src/index.spec.ts b/packages/middleware-apply-body-checksum/src/index.spec.ts index ff1fb34342a..09cdf854295 100644 --- a/packages/middleware-apply-body-checksum/src/index.spec.ts +++ b/packages/middleware-apply-body-checksum/src/index.spec.ts @@ -1,8 +1,17 @@ -import { describe, expect, test as it } from "vitest"; +import { describe, expect, test as it, vi } from "vitest"; -import { applyMd5BodyChecksumMiddleware } from "./index"; +import { applyMd5BodyChecksumMiddleware, resolveMd5BodyChecksumConfig } from "./index"; describe("middleware-apply-body-checksum package exports", () => { + it("maintains object custody", () => { + const input = { + md5: vi.fn(), + base64Encoder: vi.fn(), + streamHasher: vi.fn(), + }; + expect(resolveMd5BodyChecksumConfig(input)).toBe(input); + }); + it("applyMd5BodyChecksumMiddleware", () => { expect(typeof applyMd5BodyChecksumMiddleware).toBe("function"); }); diff --git a/packages/middleware-compression/src/resolveCompressionConfig.spec.ts b/packages/middleware-compression/src/resolveCompressionConfig.spec.ts index db62bd4a61b..6923c9bc731 100644 --- a/packages/middleware-compression/src/resolveCompressionConfig.spec.ts +++ b/packages/middleware-compression/src/resolveCompressionConfig.spec.ts @@ -9,6 +9,14 @@ describe(resolveCompressionConfig.name, () => { requestMinCompressionSizeBytes: 0, }; + it("maintains object custody", () => { + const input = { + disableRequestCompression: false, + requestMinCompressionSizeBytes: 10_000, + }; + expect(resolveCompressionConfig(input)).toBe(input); + }); + it("should throw an error if requestMinCompressionSizeBytes is less than 0", async () => { const requestMinCompressionSizeBytes = -1; const resolvedConfig = resolveCompressionConfig({ ...mockConfig, requestMinCompressionSizeBytes }); diff --git a/packages/middleware-compression/src/resolveCompressionConfig.ts b/packages/middleware-compression/src/resolveCompressionConfig.ts index 67aa028c150..cfc9c8b2e03 100644 --- a/packages/middleware-compression/src/resolveCompressionConfig.ts +++ b/packages/middleware-compression/src/resolveCompressionConfig.ts @@ -7,21 +7,23 @@ import { CompressionInputConfig, CompressionResolvedConfig } from "./configurati */ export const resolveCompressionConfig = ( input: T & Required -): T & CompressionResolvedConfig => ({ - ...input, - disableRequestCompression: normalizeProvider(input.disableRequestCompression), - requestMinCompressionSizeBytes: async () => { - const requestMinCompressionSizeBytes = await normalizeProvider(input.requestMinCompressionSizeBytes)(); +): T & CompressionResolvedConfig => { + const { disableRequestCompression, requestMinCompressionSizeBytes: _requestMinCompressionSizeBytes } = input; + return Object.assign(input, { + disableRequestCompression: normalizeProvider(disableRequestCompression), + requestMinCompressionSizeBytes: async () => { + const requestMinCompressionSizeBytes = await normalizeProvider(_requestMinCompressionSizeBytes)(); - // The requestMinCompressionSizeBytes should be less than the upper limit for API Gateway - // https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-openapi-minimum-compression-size.html - if (requestMinCompressionSizeBytes < 0 || requestMinCompressionSizeBytes > 10485760) { - throw new RangeError( - "The value for requestMinCompressionSizeBytes must be between 0 and 10485760 inclusive. " + - `The provided value ${requestMinCompressionSizeBytes} is outside this range."` - ); - } + // The requestMinCompressionSizeBytes should be less than the upper limit for API Gateway + // https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-openapi-minimum-compression-size.html + if (requestMinCompressionSizeBytes < 0 || requestMinCompressionSizeBytes > 10485760) { + throw new RangeError( + "The value for requestMinCompressionSizeBytes must be between 0 and 10485760 inclusive. " + + `The provided value ${requestMinCompressionSizeBytes} is outside this range."` + ); + } - return requestMinCompressionSizeBytes; - }, -}); + return requestMinCompressionSizeBytes; + }, + }); +}; diff --git a/packages/middleware-endpoint/src/resolveEndpointConfig.spec.ts b/packages/middleware-endpoint/src/resolveEndpointConfig.spec.ts new file mode 100644 index 00000000000..c3a9fd014b1 --- /dev/null +++ b/packages/middleware-endpoint/src/resolveEndpointConfig.spec.ts @@ -0,0 +1,17 @@ +import { describe, expect, test as it, vi } from "vitest"; + +import { resolveEndpointConfig } from "./resolveEndpointConfig"; + +describe(resolveEndpointConfig.name, () => { + it("maintains object custody", () => { + const input = { + tls: true, + useFipsEndpoint: true, + useDualstackEndpoint: true, + endpointProvider: vi.fn(), + urlParser: vi.fn(), + region: async () => "us-east-1", + }; + expect(resolveEndpointConfig(input)).toBe(input); + }); +}); diff --git a/packages/middleware-endpoint/src/resolveEndpointConfig.ts b/packages/middleware-endpoint/src/resolveEndpointConfig.ts index 30c88309a94..5935fad1c3d 100644 --- a/packages/middleware-endpoint/src/resolveEndpointConfig.ts +++ b/packages/middleware-endpoint/src/resolveEndpointConfig.ts @@ -121,21 +121,20 @@ export const resolveEndpointConfig = & PreviouslyResolved

): T & EndpointResolvedConfig

=> { const tls = input.tls ?? true; - const { endpoint } = input; + const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input; const customEndpointProvider = endpoint != null ? async () => toEndpointV1(await normalizeProvider(endpoint)()) : undefined; const isCustomEndpoint = !!endpoint; - const resolvedConfig = { - ...input, + const resolvedConfig = Object.assign(input, { endpoint: customEndpointProvider, tls, isCustomEndpoint, - useDualstackEndpoint: normalizeProvider(input.useDualstackEndpoint ?? false), - useFipsEndpoint: normalizeProvider(input.useFipsEndpoint ?? false), - } as T & EndpointResolvedConfig

; + useDualstackEndpoint: normalizeProvider(useDualstackEndpoint ?? false), + useFipsEndpoint: normalizeProvider(useFipsEndpoint ?? false), + }) as T & EndpointResolvedConfig

; let configuredEndpointPromise: undefined | Promise = undefined; resolvedConfig.serviceConfiguredEndpoint = async () => { diff --git a/packages/middleware-retry/src/configurations.spec.ts b/packages/middleware-retry/src/configurations.spec.ts index 98d8a185bd1..4131c1c18b3 100644 --- a/packages/middleware-retry/src/configurations.spec.ts +++ b/packages/middleware-retry/src/configurations.spec.ts @@ -26,6 +26,13 @@ describe(resolveRetryConfig.name, () => { vi.clearAllMocks(); }); + it("maintains object custody", () => { + const input = { + retryMode: "STANDARD", + }; + expect(resolveRetryConfig(input)).toBe(input); + }); + describe("maxAttempts", () => { it.each([1, 2, 3])("assigns provided value %s", async (maxAttempts) => { const output = await resolveRetryConfig({ maxAttempts, retryMode }).maxAttempts(); diff --git a/packages/middleware-retry/src/configurations.ts b/packages/middleware-retry/src/configurations.ts index f4c42e0964b..5a98a313a09 100644 --- a/packages/middleware-retry/src/configurations.ts +++ b/packages/middleware-retry/src/configurations.ts @@ -86,22 +86,22 @@ export interface RetryResolvedConfig { * @internal */ export const resolveRetryConfig = (input: T & PreviouslyResolved & RetryInputConfig): T & RetryResolvedConfig => { - const { retryStrategy } = input; - const maxAttempts = normalizeProvider(input.maxAttempts ?? DEFAULT_MAX_ATTEMPTS); - return { - ...input, + const { retryStrategy, retryMode: _retryMode, maxAttempts: _maxAttempts } = input; + const maxAttempts = normalizeProvider(_maxAttempts ?? DEFAULT_MAX_ATTEMPTS); + + return Object.assign(input, { maxAttempts, retryStrategy: async () => { if (retryStrategy) { return retryStrategy; } - const retryMode = await normalizeProvider(input.retryMode)(); + const retryMode = await normalizeProvider(_retryMode)(); if (retryMode === RETRY_MODES.ADAPTIVE) { return new AdaptiveRetryStrategy(maxAttempts); } return new StandardRetryStrategy(maxAttempts); }, - }; + }); }; /** diff --git a/packages/protocol-http/src/extensions/httpExtensionConfiguration.ts b/packages/protocol-http/src/extensions/httpExtensionConfiguration.ts index e002a8156a7..e4ba3b3ef71 100644 --- a/packages/protocol-http/src/extensions/httpExtensionConfiguration.ts +++ b/packages/protocol-http/src/extensions/httpExtensionConfiguration.ts @@ -25,19 +25,18 @@ export type HttpHandlerExtensionConfigType = export const getHttpHandlerExtensionConfiguration = ( runtimeConfig: HttpHandlerExtensionConfigType ) => { - let httpHandler = runtimeConfig.httpHandler!; return { setHttpHandler(handler: HttpHandler): void { - httpHandler = handler; + runtimeConfig.httpHandler = handler; }, httpHandler(): HttpHandler { - return httpHandler; + return runtimeConfig.httpHandler!; }, updateHttpClientConfig(key: keyof HandlerConfig, value: HandlerConfig[typeof key]): void { - httpHandler.updateHttpClientConfig(key, value); + runtimeConfig.httpHandler?.updateHttpClientConfig(key, value); }, httpHandlerConfigs(): HandlerConfig { - return httpHandler.httpHandlerConfigs(); + return runtimeConfig.httpHandler!.httpHandlerConfigs(); }, }; }; diff --git a/packages/smithy-client/src/client.ts b/packages/smithy-client/src/client.ts index aa12da841ac..bd05e65faa7 100644 --- a/packages/smithy-client/src/client.ts +++ b/packages/smithy-client/src/client.ts @@ -63,6 +63,16 @@ export class Client< > implements IClient { public middlewareStack: MiddlewareStack = constructStack(); + + /** + * Holds an object reference to the initial configuration object. + * Used to check that the config resolver stack does not create + * dangling instances of an intermediate form of the configuration object. + * + * @internal + */ + public initConfig?: object; + /** * May be used to cache the resolved handler function for a Command class. */ diff --git a/packages/smithy-client/src/extensions/checksum.ts b/packages/smithy-client/src/extensions/checksum.ts index 46bf5842efb..3c205c32d96 100644 --- a/packages/smithy-client/src/extensions/checksum.ts +++ b/packages/smithy-client/src/extensions/checksum.ts @@ -32,12 +32,11 @@ export const getChecksumConfiguration = (runtimeConfig: PartialChecksumRuntimeCo } return { - _checksumAlgorithms: checksumAlgorithms, addChecksumAlgorithm(algo: ChecksumAlgorithm): void { - this._checksumAlgorithms.push(algo); + checksumAlgorithms.push(algo); }, checksumAlgorithms(): ChecksumAlgorithm[] { - return this._checksumAlgorithms; + return checksumAlgorithms; }, }; }; diff --git a/packages/smithy-client/src/extensions/defaultExtensionConfiguration.ts b/packages/smithy-client/src/extensions/defaultExtensionConfiguration.ts index 1ca86487232..5572294f841 100644 --- a/packages/smithy-client/src/extensions/defaultExtensionConfiguration.ts +++ b/packages/smithy-client/src/extensions/defaultExtensionConfiguration.ts @@ -14,10 +14,7 @@ export type DefaultExtensionRuntimeConfigType = PartialRetryRuntimeConfigType & * Helper function to resolve default extension configuration from runtime config */ export const getDefaultExtensionConfiguration = (runtimeConfig: DefaultExtensionRuntimeConfigType) => { - return { - ...getChecksumConfiguration(runtimeConfig), - ...getRetryConfiguration(runtimeConfig), - }; + return Object.assign(getChecksumConfiguration(runtimeConfig), getRetryConfiguration(runtimeConfig)); }; /** @@ -36,8 +33,5 @@ export const getDefaultClientConfiguration = getDefaultExtensionConfiguration; export const resolveDefaultRuntimeConfig = ( config: DefaultExtensionConfiguration ): DefaultExtensionRuntimeConfigType => { - return { - ...resolveChecksumRuntimeConfig(config), - ...resolveRetryRuntimeConfig(config), - }; + return Object.assign(resolveChecksumRuntimeConfig(config), resolveRetryRuntimeConfig(config)); }; diff --git a/packages/smithy-client/src/extensions/retry.ts b/packages/smithy-client/src/extensions/retry.ts index bd19aea1d44..a7734d9e00e 100644 --- a/packages/smithy-client/src/extensions/retry.ts +++ b/packages/smithy-client/src/extensions/retry.ts @@ -9,13 +9,12 @@ export type PartialRetryRuntimeConfigType = Partial<{ retryStrategy: Provider { - let _retryStrategy = runtimeConfig.retryStrategy!; return { setRetryStrategy(retryStrategy: Provider): void { - _retryStrategy = retryStrategy; + runtimeConfig.retryStrategy = retryStrategy; }, retryStrategy(): Provider { - return _retryStrategy; + return runtimeConfig.retryStrategy!; }, }; }; diff --git a/packages/types/src/extensions/checksum.ts b/packages/types/src/extensions/checksum.ts index 43f34c1a66e..9861e90f638 100644 --- a/packages/types/src/extensions/checksum.ts +++ b/packages/types/src/extensions/checksum.ts @@ -77,12 +77,11 @@ export const getChecksumConfiguration: GetChecksumConfigurationType = ( } return { - _checksumAlgorithms: checksumAlgorithms, addChecksumAlgorithm(algo: ChecksumAlgorithm): void { - this._checksumAlgorithms.push(algo); + checksumAlgorithms.push(algo); }, checksumAlgorithms(): ChecksumAlgorithm[] { - return this._checksumAlgorithms; + return checksumAlgorithms; }, }; }; diff --git a/packages/types/src/extensions/defaultClientConfiguration.ts b/packages/types/src/extensions/defaultClientConfiguration.ts index f10b92806d4..892fad85b9d 100644 --- a/packages/types/src/extensions/defaultClientConfiguration.ts +++ b/packages/types/src/extensions/defaultClientConfiguration.ts @@ -21,9 +21,7 @@ type GetDefaultConfigurationType = (runtimeConfig: any) => DefaultClientConfigur * */ export const getDefaultClientConfiguration: GetDefaultConfigurationType = (runtimeConfig: any) => { - return { - ...getChecksumConfiguration(runtimeConfig), - }; + return getChecksumConfiguration(runtimeConfig); }; /** @@ -38,7 +36,5 @@ type ResolveDefaultRuntimeConfigType = (clientConfig: DefaultClientConfiguration * Helper function to resolve runtime config from default client configuration */ export const resolveDefaultRuntimeConfig: ResolveDefaultRuntimeConfigType = (config: DefaultClientConfiguration) => { - return { - ...resolveChecksumRuntimeConfig(config), - }; + return resolveChecksumRuntimeConfig(config); }; diff --git a/packages/util-stream/src/createBufferedReadable.ts b/packages/util-stream/src/createBufferedReadable.ts index 00d70592e9b..9c34b0db21f 100644 --- a/packages/util-stream/src/createBufferedReadable.ts +++ b/packages/util-stream/src/createBufferedReadable.ts @@ -36,7 +36,7 @@ export function createBufferedReadable( let mode: Modes | -1 = -1; upstream.on("data", (chunk) => { - const chunkMode = modeOf(chunk); + const chunkMode = modeOf(chunk, true); if (mode !== chunkMode) { if (mode >= 0) { downstream.push(flush(buffers, mode)); diff --git a/packages/util-stream/src/createBufferedReadableStream.ts b/packages/util-stream/src/createBufferedReadableStream.ts index b5e09029bef..23f7929cf09 100644 --- a/packages/util-stream/src/createBufferedReadableStream.ts +++ b/packages/util-stream/src/createBufferedReadableStream.ts @@ -10,7 +10,7 @@ export type Modes = 0 | 1 | 2; * @internal * @param upstream - any ReadableStream. * @param size - byte or character length minimum. Buffering occurs when a chunk fails to meet this value. - * @param onBuffer - for emitting warnings when buffering occurs. + * @param logger - for emitting warnings when buffering occurs. * @returns another stream of the same data, but buffers chunks until * the minimum size is met, except for the last chunk. */ @@ -35,7 +35,7 @@ export function createBufferedReadableStream(upstream: ReadableStream, size: num } controller.close(); } else { - const chunkMode = modeOf(chunk); + const chunkMode = modeOf(chunk, false); if (mode !== chunkMode) { if (mode >= 0) { controller.enqueue(flush(buffers, mode)); @@ -135,10 +135,11 @@ export function sizeOf(chunk?: { byteLength?: number; length?: number }): number /** * @internal * @param chunk - from upstream Readable. + * @param allowBuffer - allow mode 2 (Buffer), otherwise Buffer will return mode 1. * @returns type index of the chunk. */ -export function modeOf(chunk: BufferUnion): Modes | -1 { - if (typeof Buffer !== "undefined" && chunk instanceof Buffer) { +export function modeOf(chunk: BufferUnion, allowBuffer = true): Modes | -1 { + if (allowBuffer && typeof Buffer !== "undefined" && chunk instanceof Buffer) { return 2; } if (chunk instanceof Uint8Array) {