diff --git a/codegen/.vscode/settings.json b/codegen/.vscode/settings.json new file mode 100644 index 0000000000000..955b6b3bf727b --- /dev/null +++ b/codegen/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "java.project.referencedLibraries": [ + "lib/**/*.jar", + "/home/ec2-user/workspace/smithy-typescript/**/*.jar", + "/home/ec2-user/workspace/smithy/**/*.jar" + ], + "java.checkstyle.configuration": "${workspaceFolder}/config/checkstyle/checkstyle.xml" +} diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddDefaultUserAgentConfig.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddDefaultUserAgentConfig.java new file mode 100644 index 0000000000000..45099fe2c26b0 --- /dev/null +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddDefaultUserAgentConfig.java @@ -0,0 +1,84 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.aws.typescript.codegen; + +import java.util.Collections; +import java.util.Map; +import java.util.function.Consumer; +import software.amazon.smithy.codegen.core.SymbolProvider; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.typescript.codegen.LanguageTarget; +import software.amazon.smithy.typescript.codegen.TypeScriptSettings; +import software.amazon.smithy.typescript.codegen.TypeScriptWriter; +import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration; +import software.amazon.smithy.utils.MapUtils; + +/** + * Adds default user agent to AWS clients + */ +public final class AddDefaultUserAgentConfig implements TypeScriptIntegration { + + @Override + public void addConfigInterfaceFields( + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + TypeScriptWriter writer + ) { + writer.writeDocs("The string that will be used to populate default value in 'User-Agent' header"); + writer.write("defaultUserAgent?: string;\n"); + } + + @Override + public Map> getRuntimeConfigWriters( + TypeScriptSettings settings, + Model model, + SymbolProvider symbolProvider, + LanguageTarget target + ) { + switch (target) { + case NODE: + return MapUtils.of( + "defaultUserAgent", writer -> { + writer.addDependency(AwsDependency.AWS_SDK_UTIL_USER_AGENT_NODE.dependency); + writer.addImport("defaultUserAgent", "defaultUserAgent", AwsDependency.AWS_SDK_UTIL_USER_AGENT_NODE.packageName); + writer.addDefaultImport("packageInfo", "./package.json"); + writer.write("defaultUserAgent: defaultUserAgent(packageInfo.name, packageInfo.version),"); + } + ); + case BROWSER: + return MapUtils.of( + "defaultUserAgent", writer -> { + writer.addDependency(AwsDependency.AWS_SDK_UTIL_USER_AGENT_BROWSER.dependency); + writer.addImport("defaultUserAgent", "defaultUserAgent", AwsDependency.AWS_SDK_UTIL_USER_AGENT_BROWSER.packageName); + writer.addDefaultImport("packageInfo", "./package.json"); + writer.write("defaultUserAgent: defaultUserAgent(packageInfo.name, packageInfo.version),"); + } + ); + case REACT_NATIVE: + return MapUtils.of( + "defaultUserAgent", writer -> { + writer.addDependency(AwsDependency.AWS_SDK_UTIL_USER_AGENT_BROWSER.dependency); + writer.addImport("defaultUserAgent", "defaultUserAgent", AwsDependency.AWS_SDK_UTIL_USER_AGENT_BROWSER.packageName); + writer.addDefaultImport("packageInfo", "./package.json"); + writer.write("defaultUserAgent: defaultUserAgent(packageInfo.name, packageInfo.version),"); + } + ); + default: + return Collections.emptyMap(); + } + } +} diff --git a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsDependency.java b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsDependency.java index 773be39d70c54..99ce0fb2d44dc 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsDependency.java +++ b/codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AwsDependency.java @@ -29,39 +29,41 @@ */ public enum AwsDependency implements SymbolDependencyContainer { - MIDDLEWARE_SIGNING(NORMAL_DEPENDENCY, "@aws-sdk/middleware-signing", "^1.0.0-beta.1"), - CREDENTIAL_PROVIDER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/credential-provider-node", "^1.0.0-beta.1"), - ACCEPT_HEADER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-api-gateway", "^1.0.0-beta.1"), - S3_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-s3", "^1.0.0-beta.1"), - ADD_EXPECT_CONTINUE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-expect-continue", "^1.0.0-beta.1"), - GLACIER_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-glacier", "^1.0.0-beta.1"), - MACHINELEARNING_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-machinelearning", "^1.0.0-beta.1"), - S3_CONTROL_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-s3-control", "^1.0.0-beta.1"), - SSEC_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-ssec", "^1.0.0-beta.1"), - RDS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-rds", "^1.0.0-beta.1"), - LOCATION_CONSTRAINT(NORMAL_DEPENDENCY, "@aws-sdk/middleware-location-constraint", "^1.0.0-beta.1"), - MD5_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/md5-js", "^1.0.0-beta.1"), - STREAM_HASHER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/hash-stream-node", "^1.0.0-beta.1"), - STREAM_HASHER_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/hash-blob-browser", "^1.0.0-beta.1"), - ROUTE53_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-route53", "^1.0.0-beta.1"), - EC2_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-ec2", "^1.0.0-beta.0"), - BUCKET_ENDPOINT_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-bucket-endpoint", "^1.0.0-beta.1"), - BODY_CHECKSUM(NORMAL_DEPENDENCY, "@aws-sdk/middleware-apply-body-checksum", "^1.0.0-beta.1"), - MIDDLEWARE_HOST_HEADER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-host-header", "^1.0.0-beta.1"), - SQS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-sqs", "^1.0.0-beta.0"), - BODY_CHECKSUM_GENERATOR_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/body-checksum-browser", "^1.0.0-beta.0"), - BODY_CHECKSUM_GENERATOR_NODE(NORMAL_DEPENDENCY, "@aws-sdk/body-checksum-node", "^1.0.0-beta.0"), - XML_BUILDER(NORMAL_DEPENDENCY, "@aws-sdk/xml-builder", "^1.0.0-beta.1"), + MIDDLEWARE_SIGNING(NORMAL_DEPENDENCY, "@aws-sdk/middleware-signing", "^1.0.0-rc.1"), + CREDENTIAL_PROVIDER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/credential-provider-node", "^1.0.0-rc.1"), + ACCEPT_HEADER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-api-gateway", "^1.0.0-rc.1"), + S3_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-s3", "^1.0.0-rc.1"), + ADD_EXPECT_CONTINUE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-expect-continue", "^1.0.0-rc.1"), + GLACIER_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-glacier", "^1.0.0-rc.1"), + MACHINELEARNING_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-machinelearning", "^1.0.0-rc.1"), + S3_CONTROL_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-s3-control", "^1.0.0-rc.1"), + SSEC_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-ssec", "^1.0.0-rc.1"), + RDS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-rds", "^1.0.0-rc.1"), + LOCATION_CONSTRAINT(NORMAL_DEPENDENCY, "@aws-sdk/middleware-location-constraint", "^1.0.0-rc.1"), + MD5_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/md5-js", "^1.0.0-rc.1"), + STREAM_HASHER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/hash-stream-node", "^1.0.0-rc.1"), + STREAM_HASHER_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/hash-blob-browser", "^1.0.0-rc.1"), + ROUTE53_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-route53", "^1.0.0-rc.1"), + EC2_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-ec2", "^1.0.0-rc.1"), + BUCKET_ENDPOINT_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-bucket-endpoint", "^1.0.0-rc.1"), + BODY_CHECKSUM(NORMAL_DEPENDENCY, "@aws-sdk/middleware-apply-body-checksum", "^1.0.0-rc.1"), + MIDDLEWARE_HOST_HEADER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-host-header", "^1.0.0-rc.1"), + SQS_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-sqs", "^1.0.0-rc.1"), + BODY_CHECKSUM_GENERATOR_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/body-checksum-browser", "^1.0.0-rc.1"), + BODY_CHECKSUM_GENERATOR_NODE(NORMAL_DEPENDENCY, "@aws-sdk/body-checksum-node", "^1.0.0-rc.1"), + XML_BUILDER(NORMAL_DEPENDENCY, "@aws-sdk/xml-builder", "^1.0.0-rc.1"), XML_PARSER(NORMAL_DEPENDENCY, "fast-xml-parser", "^3.16.0"), UUID_GENERATOR(NORMAL_DEPENDENCY, "uuid", "^3.0.0"), UUID_GENERATOR_TYPES(DEV_DEPENDENCY, "@types/uuid", "^3.0.0"), - MIDDLEWARE_EVENTSTREAM(NORMAL_DEPENDENCY, "@aws-sdk/middleware-eventstream", "^1.0.0-beta.0"), - AWS_SDK_EVENTSTREAM_HANDLER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/eventstream-handler-node", "^1.0.0-beta.0"), + MIDDLEWARE_EVENTSTREAM(NORMAL_DEPENDENCY, "@aws-sdk/middleware-eventstream", "^1.0.0-rc.1"), + AWS_SDK_EVENTSTREAM_HANDLER_NODE(NORMAL_DEPENDENCY, "@aws-sdk/eventstream-handler-node", "^1.0.0-rc.1"), TRANSCRIBE_STREAMING_MIDDLEWARE(NORMAL_DEPENDENCY, "@aws-sdk/middleware-sdk-transcribe-streaming", - "^1.0.0-gamma.0"), - RETRY_CONFIG_PROVIDER(NORMAL_DEPENDENCY, "@aws-sdk/retry-config-provider", "^1.0.0-gamma.0"), - NODE_CONFIG_PROVIDER(NORMAL_DEPENDENCY, "@aws-sdk/node-config-provider", "^1.0.0-gamma.0"), - MIDDLEWARE_LOGGER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-logger", "^1.0.0-gamma.0"); + "^1.0.0-rc.1"), + RETRY_CONFIG_PROVIDER(NORMAL_DEPENDENCY, "@aws-sdk/retry-config-provider", "^1.0.0-rc.1"), + NODE_CONFIG_PROVIDER(NORMAL_DEPENDENCY, "@aws-sdk/node-config-provider", "^1.0.0-rc.1"), + MIDDLEWARE_LOGGER(NORMAL_DEPENDENCY, "@aws-sdk/middleware-logger", "^1.0.0-rc.1"), + AWS_SDK_UTIL_USER_AGENT_BROWSER(NORMAL_DEPENDENCY, "@aws-sdk/util-user-agent-browser", "1.0.0-rc.1"), + AWS_SDK_UTIL_USER_AGENT_NODE(NORMAL_DEPENDENCY, "@aws-sdk/util-user-agent-node", "1.0.0-rc.1"); public final String packageName; public final String version; diff --git a/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration b/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration index e6ca0957defd3..5fb15896eb5a2 100644 --- a/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration +++ b/codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration @@ -12,3 +12,4 @@ software.amazon.smithy.aws.typescript.codegen.AddS3ControlDependency software.amazon.smithy.aws.typescript.codegen.AddEventStreamHandlingDependency software.amazon.smithy.aws.typescript.codegen.AddHttp2Dependency software.amazon.smithy.aws.typescript.codegen.AddTranscribeStreamingDependency +software.amazon.smithy.aws.typescript.codegen.AddDefaultUserAgentConfig diff --git a/packages/util-user-agent-browser/src/index.spec.ts b/packages/util-user-agent-browser/src/index.spec.ts index 45666948fa7ed..b70a6c440eb52 100644 --- a/packages/util-user-agent-browser/src/index.spec.ts +++ b/packages/util-user-agent-browser/src/index.spec.ts @@ -1,14 +1,17 @@ import { defaultUserAgent } from "."; -it("should response basic node default user agent", () => { +it("should response basic browser default user agent", () => { let originUserAgent = ""; if (typeof navigator === "undefined") { navigator = {} as any; - originUserAgent = "foo/1.0"; + originUserAgent = + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"; (navigator.userAgent as any) = originUserAgent; } else { originUserAgent = navigator.userAgent; } - - expect(defaultUserAgent("client-s3-node", "0.1.0")).toBe(`aws-sdk-js-v3-client-s3-node/0.1.0 ${originUserAgent}`); + const userAgent = defaultUserAgent("client-s3", "0.1.0"); + expect(userAgent).toEqual(expect.stringContaining("aws-sdk-js/0.1.0")); + expect(userAgent).toEqual(expect.stringContaining(originUserAgent)); + expect(userAgent).toEqual(expect.stringContaining("sdk-client/client-s3")); }); diff --git a/packages/util-user-agent-browser/src/index.ts b/packages/util-user-agent-browser/src/index.ts index 5b063a7f443b7..fe08b25890fc9 100644 --- a/packages/util-user-agent-browser/src/index.ts +++ b/packages/util-user-agent-browser/src/index.ts @@ -1,5 +1,13 @@ -export function defaultUserAgent(packageName: string, packageVersion: string): string { - const originUserAgent = - typeof navigator !== "undefined" && typeof navigator.userAgent === "string" ? navigator.userAgent : ""; - return `aws-sdk-js-v3-${packageName}/${packageVersion} ${originUserAgent}`; -} +export const defaultUserAgent = (packageName: string, packageVersion: string): string => + [ + // sdk-metadata + // TODO: remove this post GA and version changed to 3.x.x + `aws-sdk-js/${packageVersion.replace(/^1\./, "3.")}`, + // os-metadata + window?.navigator?.product, + window?.navigator?.userAgent, + // language-metadata + `sdk-client/${packageName}`, + ] + .filter((section) => section && section.length > 0) + .join(" "); diff --git a/packages/util-user-agent-node/src/index.spec.ts b/packages/util-user-agent-node/src/index.spec.ts index 8f0a625608485..c8fec558e382d 100644 --- a/packages/util-user-agent-node/src/index.spec.ts +++ b/packages/util-user-agent-node/src/index.spec.ts @@ -6,18 +6,19 @@ describe("defaultUserAgent", () => { it("should response basic node default user agent", () => { const originEnv = process.env.AWS_EXECUTION_ENV; delete process.env.AWS_EXECUTION_ENV; - expect(defaultUserAgent("client-s3-node", "0.1.0")).toBe( - `aws-sdk-nodejs-v3-client-s3-node/0.1.0 ${process.platform}/${process.version}` - ); + const userAgent = defaultUserAgent("client-s3", "0.1.0"); + expect(userAgent).toEqual(expect.stringContaining("aws-sdk-nodejs/0.1.0")); + expect(userAgent).toEqual(expect.stringContaining(process.platform)); + expect(userAgent).toEqual(expect.stringContaining(`nodejs/${process.versions.node}`)); + expect(userAgent).toEqual(expect.stringContaining("sdk-client/client-s3")); if (originEnv) process.env.AWS_EXECUTION_ENV = originEnv; }); it("should add AWS_EXECUTION_ENV", () => { const originEnv = process.env.AWS_EXECUTION_ENV; process.env.AWS_EXECUTION_ENV = "ecs"; - expect(defaultUserAgent("client-s3-node", "0.1.0")).toBe( - `aws-sdk-nodejs-v3-client-s3-node/0.1.0 ${process.platform}/${process.version} exec-env/ecs` - ); + const userAgent = defaultUserAgent("client-s3", "0.1.0"); + expect(userAgent).toEqual(expect.stringContaining("exec-env/ecs")); if (originEnv) process.env.AWS_EXECUTION_ENV = originEnv; }); }); diff --git a/packages/util-user-agent-node/src/index.ts b/packages/util-user-agent-node/src/index.ts index 0540099bff7ed..f43e428f1a457 100644 --- a/packages/util-user-agent-node/src/index.ts +++ b/packages/util-user-agent-node/src/index.ts @@ -1,9 +1,17 @@ import process from "process"; -export function defaultUserAgent(packageName: string, packageVersion: string): string { - let engine = `${process.platform}/${process.version}`; - if (process.env.AWS_EXECUTION_ENV) { - engine += ` exec-env/${process.env.AWS_EXECUTION_ENV}`; - } - return `aws-sdk-nodejs-v3-${packageName}/${packageVersion} ${engine}`; -} +export const defaultUserAgent = (packageName: string, packageVersion: string): string => + [ + // sdk-metadata + // TODO: remove this post GA and version changed to 3.x.x + `aws-sdk-nodejs/${packageVersion.replace(/^1\./, "3.")}`, + // os-metadata + process.platform, + `nodejs/${process.versions.node}`, + // language-metadata + `sdk-client/${packageName}`, + // env-metadata + process.env.AWS_EXECUTION_ENV ? `exec-env/${process.env.AWS_EXECUTION_ENV}` : undefined, + ] + .filter((section) => section && section.length > 0) + .join(" ");