Skip to content

fix(packages): maintain singleton config object #6959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { describe, expect, test as it } from "vitest";

import { resolveAccountIdEndpointModeConfig } from "./AccountIdEndpointModeConfigResolver";

describe(resolveAccountIdEndpointModeConfig.name, () => {
it("maintains object custody", () => {
const input = {};
expect(resolveAccountIdEndpointModeConfig(input)).toBe(input);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@ export interface AccountIdEndpointModeResolvedConfig {
export const resolveAccountIdEndpointModeConfig = <T>(
input: T & AccountIdEndpointModeInputConfig & PreviouslyResolved
): T & AccountIdEndpointModeResolvedConfig => {
const accountIdEndpointModeProvider = normalizeProvider(
input.accountIdEndpointMode ?? DEFAULT_ACCOUNT_ID_ENDPOINT_MODE
);
return {
...input,
const { accountIdEndpointMode } = input;
const accountIdEndpointModeProvider = normalizeProvider(accountIdEndpointMode ?? DEFAULT_ACCOUNT_ID_ENDPOINT_MODE);
return Object.assign(input, {
accountIdEndpointMode: async () => {
const accIdMode = await accountIdEndpointModeProvider();
if (!validateAccountIdEndpointMode(accIdMode)) {
Expand All @@ -49,5 +47,5 @@ export const resolveAccountIdEndpointModeConfig = <T>(
}
return accIdMode;
},
};
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@ describe(resolveAwsSdkSigV4AConfig.name, () => {
expect(typeof config.sigv4aSigningRegionSet).toEqual("function");
expect(await config.sigv4aSigningRegionSet()).toEqual(undefined);
});

it("maintains object custody", () => {
const input = {};
expect(resolveAwsSdkSigV4AConfig(input)).toBe(input);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ import { describe, expect, test as it, vi } from "vitest";
import { resolveAwsSdkSigV4Config } from "./resolveAwsSdkSigV4Config";

describe(resolveAwsSdkSigV4Config.name, () => {
it("maintains object custody", () => {
const input = {
region: "",
sha256: vi.fn(),
serviceId: "",
useFipsEndpoint: async () => false,
useDualstackEndpoint: async () => false,
};
expect(resolveAwsSdkSigV4Config(input)).toBe(input);
});

it("should allow one argument to be passed to the resolved credentials function", async () => {
const fn = vi.fn();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ export const resolveAwsSdkSigV4Config = <T>(
};
}

return {
...config,
return Object.assign(config, {
systemClockOffset,
signingEscapePath,
credentials: isUserSupplied
Expand All @@ -232,7 +231,7 @@ export const resolveAwsSdkSigV4Config = <T>(
)
: boundCredentialsProvider!,
signer,
};
});
};

/**
Expand Down
6 changes: 6 additions & 0 deletions packages/middleware-api-key/src/apiKeyConfiguration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { describe, expect, test as it } from "vitest";
import { resolveApiKeyConfig } from "./index";

describe("ApiKeyConfig", () => {
it("maintains object custody", () => {
const config = {
apiKey: () => Promise.resolve("example-api-key"),
};
expect(resolveApiKeyConfig(config)).toBe(config);
});
it("should return the input unchanged", () => {
const config = {
apiKey: () => Promise.resolve("example-api-key"),
Expand Down
8 changes: 4 additions & 4 deletions packages/middleware-api-key/src/apiKeyConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export interface ApiKeyResolvedConfig {
export const resolveApiKeyConfig = <T>(
input: T & ApiKeyPreviouslyResolved & ApiKeyInputConfig
): T & ApiKeyResolvedConfig => {
return {
...input,
apiKey: input.apiKey ? normalizeProvider(input.apiKey) : undefined,
};
const { apiKey } = input;
return Object.assign(input, {
apiKey: apiKey ? normalizeProvider(apiKey) : undefined,
});
};
15 changes: 15 additions & 0 deletions packages/middleware-bucket-endpoint/src/configurations.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test as it, vi } from "vitest";

import { resolveBucketEndpointConfig } from "./configurations";

describe(resolveBucketEndpointConfig.name, () => {
it("maintains object custody", () => {
const input = {
region: async () => "",
regionInfoProvider: vi.fn(),
useFipsEndpoint: async () => false,
useDualstackEndpoint: async () => false,
};
expect(resolveBucketEndpointConfig(input)).toBe(input);
});
});
5 changes: 2 additions & 3 deletions packages/middleware-bucket-endpoint/src/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ export function resolveBucketEndpointConfig<T>(
useArnRegion = false,
disableMultiregionAccessPoints = false,
} = input;
return {
...input,
return Object.assign(input, {
bucketEndpoint,
forcePathStyle,
useAccelerateEndpoint,
Expand All @@ -103,5 +102,5 @@ export function resolveBucketEndpointConfig<T>(
typeof disableMultiregionAccessPoints === "function"
? disableMultiregionAccessPoints
: () => Promise.resolve(disableMultiregionAccessPoints),
};
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,26 @@ vi.mock("@aws-sdk/endpoint-cache");

describe(resolveEndpointDiscoveryConfig.name, () => {
const endpointDiscoveryCommandCtor = vi.fn();
const mockInput = {
const mockInput = () => ({
isCustomEndpoint: false,
credentials: vi.fn(),
endpointDiscoveryEnabledProvider: vi.fn(),
};
});

afterEach(() => {
vi.clearAllMocks();
});

it("maintains object custody", () => {
const input = {
credentials: vi.fn(),
endpointDiscoveryEnabledProvider: async () => false,
};
expect(resolveEndpointDiscoveryConfig(input, { endpointDiscoveryCommandCtor })).toBe(input);
});

it("assigns endpointDiscoveryCommandCtor in resolvedConfig", () => {
const resolvedConfig = resolveEndpointDiscoveryConfig(mockInput, { endpointDiscoveryCommandCtor });
const resolvedConfig = resolveEndpointDiscoveryConfig(mockInput(), { endpointDiscoveryCommandCtor });
expect(resolvedConfig.endpointDiscoveryCommandCtor).toStrictEqual(endpointDiscoveryCommandCtor);
});

Expand All @@ -27,7 +35,7 @@ describe(resolveEndpointDiscoveryConfig.name, () => {
const endpointCacheSize = 100;
resolveEndpointDiscoveryConfig(
{
...mockInput,
...mockInput(),
endpointCacheSize,
},
{ endpointDiscoveryCommandCtor }
Expand All @@ -36,28 +44,30 @@ describe(resolveEndpointDiscoveryConfig.name, () => {
});

it("creates cache of size 1000 if endpointCacheSize not passed", () => {
resolveEndpointDiscoveryConfig(mockInput, { endpointDiscoveryCommandCtor });
resolveEndpointDiscoveryConfig(mockInput(), { endpointDiscoveryCommandCtor });
expect(EndpointCache).toBeCalledWith(1000);
});
});

describe("endpointDiscoveryEnabled", () => {
it.each<boolean>([false, true])(`sets to value passed in the config: %s`, async (endpointDiscoveryEnabled) => {
const input = mockInput();
const resolvedConfig = resolveEndpointDiscoveryConfig(
{
...mockInput,
...input,
endpointDiscoveryEnabled,
},
{ endpointDiscoveryCommandCtor }
);
await expect(resolvedConfig.endpointDiscoveryEnabled()).resolves.toBe(endpointDiscoveryEnabled);
expect(mockInput.endpointDiscoveryEnabledProvider).not.toHaveBeenCalled();
expect(input.endpointDiscoveryEnabledProvider).not.toHaveBeenCalled();
expect(resolvedConfig.isClientEndpointDiscoveryEnabled).toStrictEqual(true);
});

it(`sets to endpointDiscoveryEnabledProvider if value is not passed`, () => {
const resolvedConfig = resolveEndpointDiscoveryConfig(mockInput, { endpointDiscoveryCommandCtor });
expect(resolvedConfig.endpointDiscoveryEnabled).toBe(mockInput.endpointDiscoveryEnabledProvider);
const input = mockInput();
const resolvedConfig = resolveEndpointDiscoveryConfig(input, { endpointDiscoveryCommandCtor });
expect(resolvedConfig.endpointDiscoveryEnabled).toBe(input.endpointDiscoveryEnabledProvider);
expect(resolvedConfig.isClientEndpointDiscoveryEnabled).toStrictEqual(false);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,16 @@ export interface EndpointDiscoveryConfigOptions {
export const resolveEndpointDiscoveryConfig = <T>(
input: T & PreviouslyResolved & EndpointDiscoveryInputConfig,
{ endpointDiscoveryCommandCtor }: EndpointDiscoveryConfigOptions
): T & EndpointDiscoveryResolvedConfig => ({
...input,
endpointDiscoveryCommandCtor,
endpointCache: new EndpointCache(input.endpointCacheSize ?? 1000),
endpointDiscoveryEnabled:
input.endpointDiscoveryEnabled !== undefined
? () => Promise.resolve(input.endpointDiscoveryEnabled)
: input.endpointDiscoveryEnabledProvider,
isClientEndpointDiscoveryEnabled: input.endpointDiscoveryEnabled !== undefined,
});
): T & EndpointDiscoveryResolvedConfig => {
const { endpointCacheSize, endpointDiscoveryEnabled, endpointDiscoveryEnabledProvider } = input;

return Object.assign(input, {
endpointDiscoveryCommandCtor,
endpointCache: new EndpointCache(endpointCacheSize ?? 1000),
endpointDiscoveryEnabled:
endpointDiscoveryEnabled !== undefined
? () => Promise.resolve(endpointDiscoveryEnabled)
: endpointDiscoveryEnabledProvider,
isClientEndpointDiscoveryEnabled: endpointDiscoveryEnabled !== undefined,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this boolean seems wrong... what if endpointDiscoveryEnabled === false?

not related to this PR though

});
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,12 @@ export function resolveEventStreamConfig<T>(
): T & EventStreamResolvedConfig {
const eventSigner = input.signer;
const messageSigner = input.signer;
const eventStreamPayloadHandler = input.eventStreamPayloadHandlerProvider({
...input,
const newInput = Object.assign(input, {
eventSigner,
messageSigner,
});
return {
...input,
eventSigner,
const eventStreamPayloadHandler = newInput.eventStreamPayloadHandlerProvider(newInput);
return Object.assign(newInput, {
eventStreamPayloadHandler,
};
});
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { LexRuntimeV2 } from "@aws-sdk/client-lex-runtime-v2";
import { RekognitionStreaming } from "@aws-sdk/client-rekognitionstreaming";
import { TranscribeStreaming } from "@aws-sdk/client-transcribe-streaming";
import { describe, expect, test as it } from "vitest";
import { Decoder, Encoder, EventStreamPayloadHandlerProvider } from "@smithy/types";
import { describe, expect, test as it, vi } from "vitest";

import { requireRequestsFrom } from "../../../private/aws-util-test/src";
import { resolveEventStreamConfig } from "./eventStreamConfiguration";

describe("middleware-eventstream", () => {
const logger = {
Expand All @@ -14,6 +16,18 @@ describe("middleware-eventstream", () => {
error() {},
};

describe("config resolver", () => {
it("maintains object custody", () => {
const input = {
utf8Encoder: vi.fn(),
utf8Decoder: vi.fn(),
signer: vi.fn(),
eventStreamPayloadHandlerProvider: vi.fn(),
};
expect(resolveEventStreamConfig(input)).toBe(input);
});
});

// TODO: http2 in CI
describe.skip(LexRuntimeV2.name, () => {
it("should set streaming headers", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ describe(resolveFlexibleChecksumsConfig.name, () => {
vi.clearAllMocks();
});

it("maintains object custody", () => {
const input = {};
expect(resolveFlexibleChecksumsConfig(input)).toBe(input);
});

it("returns default client checksums configuration, if not provided", () => {
const resolvedConfig = resolveFlexibleChecksumsConfig({});
expect(resolvedConfig).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ export interface FlexibleChecksumsResolvedConfig {
*/
export const resolveFlexibleChecksumsConfig = <T>(
input: T & FlexibleChecksumsInputConfig
): T & FlexibleChecksumsResolvedConfig => ({
...input,
requestChecksumCalculation: normalizeProvider(
input.requestChecksumCalculation ?? DEFAULT_REQUEST_CHECKSUM_CALCULATION
),
responseChecksumValidation: normalizeProvider(
input.responseChecksumValidation ?? DEFAULT_RESPONSE_CHECKSUM_VALIDATION
),
requestStreamBufferSize: Number(input.requestStreamBufferSize ?? 0),
});
): T & FlexibleChecksumsResolvedConfig => {
const { requestChecksumCalculation, responseChecksumValidation, requestStreamBufferSize } = input;
return Object.assign(input, {
requestChecksumCalculation: normalizeProvider(requestChecksumCalculation ?? DEFAULT_REQUEST_CHECKSUM_CALCULATION),
responseChecksumValidation: normalizeProvider(responseChecksumValidation ?? DEFAULT_RESPONSE_CHECKSUM_VALIDATION),
requestStreamBufferSize: Number(requestStreamBufferSize ?? 0),
});
};
9 changes: 8 additions & 1 deletion packages/middleware-host-header/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { HttpRequest } from "@smithy/protocol-http";
import { beforeEach, describe, expect, test as it, vi } from "vitest";

import { hostHeaderMiddleware } from "./index";
import { hostHeaderMiddleware, resolveHostHeaderConfig } from "./index";
describe("hostHeaderMiddleware", () => {
const mockNextHandler = vi.fn();

beforeEach(() => {
vi.clearAllMocks();
});

it("maintains object custody", () => {
const input = {
requestHandler: vi.fn() as any,
};
expect(resolveHostHeaderConfig(input)).toBe(input);
});

it("should set host header if not already set", async () => {
expect.assertions(2);
const middleware = hostHeaderMiddleware({ requestHandler: {} as any });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ export interface LocationConstraintResolvedConfig {
export function resolveLocationConstraintConfig<T>(
input: T & LocationConstraintInputConfig & PreviouslyResolved
): T & LocationConstraintResolvedConfig {
return { ...input };
return input;
}
8 changes: 8 additions & 0 deletions packages/middleware-location-constraint/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { beforeEach, describe, expect, test as it, vi } from "vitest";

import { locationConstraintMiddleware } from "./";
import { resolveLocationConstraintConfig } from "./configuration";

describe("locationConstrainMiddleware", () => {
const next = vi.fn();
Expand All @@ -12,6 +13,13 @@ describe("locationConstrainMiddleware", () => {
vi.clearAllMocks();
});

describe("config resolver", () => {
it("maintains object custody", () => {
const input = {} as any;
expect(resolveLocationConstraintConfig(input)).toBe(input);
});
});

describe("for region us-east-1", () => {
const handler = locationConstraintMiddleware({
region: () => Promise.resolve("us-east-1"),
Expand Down
10 changes: 10 additions & 0 deletions packages/middleware-sdk-s3-control/src/configurations.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { describe, expect, test as it } from "vitest";

import { resolveS3ControlConfig } from "./configurations";

describe(resolveS3ControlConfig.name, () => {
it("maintains object custody", () => {
const input = {} as any;
expect(resolveS3ControlConfig(input)).toBe(input);
});
});
5 changes: 2 additions & 3 deletions packages/middleware-sdk-s3-control/src/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ export function resolveS3ControlConfig<T>(
input: T & PreviouslyResolved & S3ControlInputConfig
): T & S3ControlResolvedConfig {
const { useArnRegion = false } = input;
return {
...input,
return Object.assign(input, {
useArnRegion: typeof useArnRegion === "function" ? useArnRegion : () => Promise.resolve(useArnRegion),
};
});
}
Loading
Loading