From 7811cd959b611e13466c7c1f0469947ef32a3695 Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 10 Nov 2022 11:59:10 -0500 Subject: [PATCH] fix(types): add client config interface test with s3 example (#4156) * fix(types): add client config interface test with s3 example * fix(types): decouple V1orV2Endpoint type from EndpointBearer type * fix(lib-storage): type fix, allow undefined endpoint * fix(types): code reorganization in client-api-test --- lib/lib-storage/src/Upload.ts | 2 +- .../src/resolveEndpointConfig.ts | 13 ++- packages/middleware-serde/src/serdePlugin.ts | 19 ++-- .../src/serializerMiddleware.ts | 6 +- private/client-api-test/jest.config.js | 5 ++ private/client-api-test/package.json | 61 +++++++++++++ private/client-api-test/readme.md | 10 +++ .../ClientInterfaceTest.ts | 24 +++++ .../client-interface-tests/FIELD_INIT_TYPE.ts | 5 ++ .../client-s3/ClientS3InterfaceTest.spec.ts | 41 +++++++++ .../client-s3/ClientS3InterfaceTest.ts | 25 ++++++ .../client-s3/RESOLVED_FIELDS.ts | 53 +++++++++++ .../initializeWithMaximalConfiguration.ts | 87 +++++++++++++++++++ .../initializeWithMinimalConfiguration.ts | 9 ++ private/client-api-test/tsconfig.cjs.json | 6 ++ private/client-api-test/tsconfig.es.json | 8 ++ private/client-api-test/tsconfig.json | 13 +++ private/client-api-test/tsconfig.types.json | 10 +++ private/client-api-test/typedoc.json | 3 + 19 files changed, 384 insertions(+), 16 deletions(-) create mode 100644 private/client-api-test/jest.config.js create mode 100644 private/client-api-test/package.json create mode 100644 private/client-api-test/readme.md create mode 100644 private/client-api-test/src/client-interface-tests/ClientInterfaceTest.ts create mode 100644 private/client-api-test/src/client-interface-tests/FIELD_INIT_TYPE.ts create mode 100644 private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.spec.ts create mode 100644 private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.ts create mode 100644 private/client-api-test/src/client-interface-tests/client-s3/RESOLVED_FIELDS.ts create mode 100644 private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMaximalConfiguration.ts create mode 100644 private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMinimalConfiguration.ts create mode 100644 private/client-api-test/tsconfig.cjs.json create mode 100644 private/client-api-test/tsconfig.es.json create mode 100644 private/client-api-test/tsconfig.json create mode 100644 private/client-api-test/tsconfig.types.json create mode 100644 private/client-api-test/typedoc.json diff --git a/lib/lib-storage/src/Upload.ts b/lib/lib-storage/src/Upload.ts index 8ff3d1a34ce0..52686f83ded9 100644 --- a/lib/lib-storage/src/Upload.ts +++ b/lib/lib-storage/src/Upload.ts @@ -129,7 +129,7 @@ export class Upload extends EventEmitter { const resolved = await Promise.all([this.client.send(new PutObjectCommand(params)), clientConfig?.endpoint?.()]); const putResult = resolved[0]; - let endpoint: Endpoint = resolved[1]; + let endpoint: Endpoint | undefined = resolved[1]; if (!endpoint) { endpoint = toEndpointV1( diff --git a/packages/middleware-endpoint/src/resolveEndpointConfig.ts b/packages/middleware-endpoint/src/resolveEndpointConfig.ts index 4c9bf0070624..80e39a0a532c 100644 --- a/packages/middleware-endpoint/src/resolveEndpointConfig.ts +++ b/packages/middleware-endpoint/src/resolveEndpointConfig.ts @@ -47,10 +47,17 @@ interface PreviouslyResolved */ export interface EndpointResolvedConfig { /** - * Resolved value for input {@link EndpointsInputConfig.endpoint} - * @deprecated Use {@link EndpointResolvedConfig.endpointProvider} instead + * Custom endpoint provided by the user. + * This is normalized to a single interface from the various acceptable types. + * This field will be undefined if a custom endpoint is not provided. + * + * As of endpoints 2.0, this config method can not be used to resolve + * the endpoint for a service and region. + * + * @see https://github.com/aws/aws-sdk-js-v3/issues/4122 + * @deprecated Use {@link EndpointResolvedConfig.endpointProvider} instead. */ - endpoint: Provider; + endpoint?: Provider; endpointProvider: (params: T, context?: { logger?: Logger }) => EndpointV2; diff --git a/packages/middleware-serde/src/serdePlugin.ts b/packages/middleware-serde/src/serdePlugin.ts index 8a7f111d3310..b43cd8e45df4 100644 --- a/packages/middleware-serde/src/serdePlugin.ts +++ b/packages/middleware-serde/src/serdePlugin.ts @@ -5,6 +5,7 @@ import { MetadataBearer, MiddlewareStack, Pluggable, + Provider, RequestSerializer, ResponseDeserializer, SerializeHandlerOptions, @@ -30,22 +31,22 @@ export const serializerMiddlewareOption: SerializeHandlerOptions = { // Type the modifies the EndpointBearer to make it compatible with Endpoints 2.0 change. // Must be removed after all clients has been onboard the Endpoints 2.0 -export type V1OrV2Endpoint = T & { +export type V1OrV2Endpoint = { + // for v2 urlParser?: UrlParser; + + // for v1 + endpoint?: Provider; }; -export function getSerdePlugin< - InputType extends object, - SerDeContext extends EndpointBearer, - OutputType extends MetadataBearer ->( - config: V1OrV2Endpoint, - serializer: RequestSerializer, +export function getSerdePlugin( + config: V1OrV2Endpoint, + serializer: RequestSerializer, deserializer: ResponseDeserializer ): Pluggable { return { applyToStack: (commandStack: MiddlewareStack) => { - commandStack.add(deserializerMiddleware(config, deserializer), deserializerMiddlewareOption); + commandStack.add(deserializerMiddleware(config as SerDeContext, deserializer), deserializerMiddlewareOption); commandStack.add(serializerMiddleware(config, serializer), serializerMiddlewareOption); }, }; diff --git a/packages/middleware-serde/src/serializerMiddleware.ts b/packages/middleware-serde/src/serializerMiddleware.ts index 9d3fd9367bfd..e42726aa5f3b 100644 --- a/packages/middleware-serde/src/serializerMiddleware.ts +++ b/packages/middleware-serde/src/serializerMiddleware.ts @@ -12,7 +12,7 @@ import type { V1OrV2Endpoint } from "./serdePlugin"; export const serializerMiddleware = ( - options: V1OrV2Endpoint, + options: V1OrV2Endpoint, serializer: RequestSerializer ): SerializeMiddleware => (next: SerializeHandler, context: HandlerExecutionContext): SerializeHandler => @@ -20,13 +20,13 @@ export const serializerMiddleware = const endpoint = context.endpointV2?.url && options.urlParser ? async () => options.urlParser!(context.endpointV2!.url as URL) - : options.endpoint; + : options.endpoint!; if (!endpoint) { throw new Error("No valid endpoint provider available."); } - const request = await serializer(args.input, { ...options, endpoint }); + const request = await serializer(args.input, { ...options, endpoint } as RuntimeUtils); return next({ ...args, diff --git a/private/client-api-test/jest.config.js b/private/client-api-test/jest.config.js new file mode 100644 index 000000000000..a8d1c2e49912 --- /dev/null +++ b/private/client-api-test/jest.config.js @@ -0,0 +1,5 @@ +const base = require("../../jest.config.base.js"); + +module.exports = { + ...base, +}; diff --git a/private/client-api-test/package.json b/private/client-api-test/package.json new file mode 100644 index 000000000000..4408c5f4aa5d --- /dev/null +++ b/private/client-api-test/package.json @@ -0,0 +1,61 @@ +{ + "name": "@aws-sdk/client-api-test", + "description": "Test suite for client interface stability", + "version": "3.0.0", + "scripts": { + "build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'", + "build:cjs": "tsc -p tsconfig.cjs.json", + "build:docs": "typedoc", + "build:es": "tsc -p tsconfig.es.json", + "build:include:deps": "lerna run --scope $npm_package_name --include-dependencies build", + "build:types": "tsc -p tsconfig.types.json", + "build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4", + "clean": "rimraf ./dist-* && rimraf *.tsbuildinfo", + "test": "jest --coverage --passWithNoTests" + }, + "main": "./dist-cjs/index.js", + "types": "./dist-types/index.d.ts", + "module": "./dist-es/index.js", + "sideEffects": false, + "dependencies": { + "@aws-sdk/client-s3": "*", + "tslib": "^2.3.1" + }, + "devDependencies": { + "@tsconfig/node14": "1.0.3", + "@types/node": "^12.7.5", + "concurrently": "7.0.0", + "downlevel-dts": "0.10.1", + "typedoc": "0.19.2", + "typescript": "~4.6.2" + }, + "overrides": { + "typedoc": { + "typescript": "~4.6.2" + } + }, + "engines": { + "node": ">=14.0.0" + }, + "typesVersions": { + "<4.0": { + "dist-types/*": [ + "dist-types/ts3.4/*" + ] + } + }, + "files": [ + "dist-*" + ], + "author": { + "name": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "license": "Apache-2.0", + "private": true, + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-js-v3.git", + "directory": "private/client-api-test" + } +} diff --git a/private/client-api-test/readme.md b/private/client-api-test/readme.md new file mode 100644 index 000000000000..17aa532e4ba0 --- /dev/null +++ b/private/client-api-test/readme.md @@ -0,0 +1,10 @@ +# @aws-sdk/client-api-test + +This is not a runtime or published package. + +This is a test spec. + +The purpose of this package is to stabilize the `@aws-sdk/client-*` interface against changes. + +If tests in this package fail, the author should either fix their changes such that the API contract +is maintained, or appropriately announce and safely deprecate the interfaces affected by incoming changes. diff --git a/private/client-api-test/src/client-interface-tests/ClientInterfaceTest.ts b/private/client-api-test/src/client-interface-tests/ClientInterfaceTest.ts new file mode 100644 index 000000000000..df683d9ffb6c --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/ClientInterfaceTest.ts @@ -0,0 +1,24 @@ +/** + * Pattern for testing the stability of a Client interface. + */ +export interface ClientInterfaceTest { + /** + * Assert that some resolved config fields can be set to undefined. + */ + optionalConfigFieldsCanBeVoided(): void; + /** + * Create a test that initializes a client + * with the minimal number of user-supplied values. This is + * usually 0. + * + * This method is also a compilation test. + */ + initializeWithMinimalConfiguration(): Client; + /** + * Create a test that initializes a client with all config fields supplied + * by the user. + * + * This method is also a compilation test. + */ + initializeWithMaximalConfiguration(): Client; +} diff --git a/private/client-api-test/src/client-interface-tests/FIELD_INIT_TYPE.ts b/private/client-api-test/src/client-interface-tests/FIELD_INIT_TYPE.ts new file mode 100644 index 000000000000..b9df415c4167 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/FIELD_INIT_TYPE.ts @@ -0,0 +1,5 @@ +/** + * The status of a config field after passing through constructor + * resolvers. + */ +export type FIELD_INIT_TYPE = "resolvedByConfigResolver" | "resolvedOnlyIfProvided" | "neverResolved"; diff --git a/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.spec.ts b/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.spec.ts new file mode 100644 index 000000000000..47c6f328f179 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.spec.ts @@ -0,0 +1,41 @@ +import { ClientS3InterfaceTest } from "./ClientS3InterfaceTest"; +import { RESOLVED_FIELDS } from "./RESOLVED_FIELDS"; + +const Subject = ClientS3InterfaceTest; + +describe("Client config interface should be stable", () => { + describe(ClientS3InterfaceTest.name, () => { + describe("initialization with minimal configuration", () => { + const client = new Subject().initializeWithMinimalConfiguration(); + for (const [configType, fields] of Object.entries(RESOLVED_FIELDS)) { + for (const field of fields) { + if (configType === "resolvedByConfigResolver") { + it(`should resolve the field [${field}] after minimal client init`, () => { + expect(client.config[field as keyof typeof client.config]).toBeDefined(); + }); + } else { + it(`should not resolve the field [${field}] after minimal client init`, () => { + expect(client.config[field as keyof typeof client.config]).not.toBeDefined(); + }); + } + } + } + }); + describe("initialization with maximal configuration", () => { + const client = new Subject().initializeWithMaximalConfiguration(); + for (const [configType, fields] of Object.entries(RESOLVED_FIELDS)) { + for (const field of fields) { + if (configType === "resolvedByConfigResolver" || configType === "resolvedOnlyIfProvided") { + it(`should resolve the field [${field}] after maximally configured client init`, () => { + expect(client.config[field as keyof typeof client.config]).toBeDefined(); + }); + } else { + it(`should not resolve the field [${field}] after maximally configured client init`, () => { + expect(client.config[field as keyof typeof client.config]).not.toBeDefined(); + }); + } + } + } + }); + }); +}); diff --git a/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.ts b/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.ts new file mode 100644 index 000000000000..5ef04d12aaf4 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/client-s3/ClientS3InterfaceTest.ts @@ -0,0 +1,25 @@ +import { S3Client, S3ClientResolvedConfig } from "@aws-sdk/client-s3"; + +import { ClientInterfaceTest } from "../ClientInterfaceTest"; +import { initializeWithMaximalConfiguration } from "./impl/initializeWithMaximalConfiguration"; +import { initializeWithMinimalConfiguration } from "./impl/initializeWithMinimalConfiguration"; + +export class ClientS3InterfaceTest implements ClientInterfaceTest { + optionalConfigFieldsCanBeVoided(): void { + const s3 = new S3Client({}); + const resolvedConfig: S3ClientResolvedConfig = s3.config; + /** + * Endpoint is no longer guaranteed as of endpoints 2.0 (rulesets). + * @see https://github.com/aws/aws-sdk-js-v3/issues/4122 + */ + resolvedConfig.endpoint = void 0; + resolvedConfig.isCustomEndpoint = void 0; + resolvedConfig.customUserAgent = void 0; + } + initializeWithMinimalConfiguration(): S3Client { + return initializeWithMinimalConfiguration(); + } + initializeWithMaximalConfiguration(): S3Client { + return initializeWithMaximalConfiguration(); + } +} diff --git a/private/client-api-test/src/client-interface-tests/client-s3/RESOLVED_FIELDS.ts b/private/client-api-test/src/client-interface-tests/client-s3/RESOLVED_FIELDS.ts new file mode 100644 index 000000000000..fec3228a7c34 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/client-s3/RESOLVED_FIELDS.ts @@ -0,0 +1,53 @@ +import { S3ClientResolvedConfig } from "@aws-sdk/client-s3"; + +import { FIELD_INIT_TYPE } from "../FIELD_INIT_TYPE"; + +export const RESOLVED_FIELDS: Record = { + resolvedByConfigResolver: [ + "requestHandler", + "apiVersion", + "sha256", + "urlParser", + "bodyLengthChecker", + "streamCollector", + "base64Decoder", + "base64Encoder", + "utf8Decoder", + "utf8Encoder", + "runtime", + "disableHostPrefix", + "maxAttempts", + "retryMode", + "logger", + "useDualstackEndpoint", + "useFipsEndpoint", + "serviceId", + "region", + "credentialDefaultProvider", + "signingEscapePath", + "useArnRegion", + "defaultUserAgentProvider", + "streamHasher", + "md5", + "sha1", + "getAwsChunkedEncodingStream", + "eventStreamSerdeProvider", + "defaultsMode", + "sdkStreamMixin", + "endpointProvider", + "tls", + "isCustomEndpoint", + "retryStrategy", + "credentials", + "signer", + "systemClockOffset", + "forcePathStyle", + "useAccelerateEndpoint", + "disableMultiregionAccessPoints", + "eventStreamMarshaller", + "defaultSigningName", + "useGlobalEndpoint", + ], + resolvedOnlyIfProvided: ["customUserAgent", "endpoint"], + neverResolved: [], +}; diff --git a/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMaximalConfiguration.ts b/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMaximalConfiguration.ts new file mode 100644 index 000000000000..ccd4e01956c8 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMaximalConfiguration.ts @@ -0,0 +1,87 @@ +import { S3Client } from "@aws-sdk/client-s3"; +import { decorateDefaultCredentialProvider } from "@aws-sdk/client-sts"; +import { + NODE_REGION_CONFIG_FILE_OPTIONS, + NODE_REGION_CONFIG_OPTIONS, + NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, + NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, +} from "@aws-sdk/config-resolver"; +import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node"; +import { eventStreamSerdeProvider } from "@aws-sdk/eventstream-serde-node"; +import { Hash } from "@aws-sdk/hash-node"; +import { readableStreamHasher as streamHasher } from "@aws-sdk/hash-stream-node"; +import { NODE_USE_ARN_REGION_CONFIG_OPTIONS } from "@aws-sdk/middleware-bucket-endpoint"; +import { + DEFAULT_RETRY_MODE, + NODE_MAX_ATTEMPT_CONFIG_OPTIONS, + NODE_RETRY_MODE_CONFIG_OPTIONS, +} from "@aws-sdk/middleware-retry"; +import { loadConfig as loadNodeConfig } from "@aws-sdk/node-config-provider"; +import { NodeHttpHandler as RequestHandler, streamCollector } from "@aws-sdk/node-http-handler"; +import { SignatureV4MultiRegion } from "@aws-sdk/signature-v4-multi-region"; +import { loadConfigsForDefaultMode } from "@aws-sdk/smithy-client"; +import { EndpointV2 } from "@aws-sdk/types"; +import { parseUrl } from "@aws-sdk/url-parser"; +import { fromBase64, toBase64 } from "@aws-sdk/util-base64"; +import { calculateBodyLength } from "@aws-sdk/util-body-length-node"; +import { resolveDefaultsModeConfig } from "@aws-sdk/util-defaults-mode-node"; +import { getAwsChunkedEncodingStream, sdkStreamMixin } from "@aws-sdk/util-stream-node"; +import { defaultUserAgent } from "@aws-sdk/util-user-agent-node"; +import { fromUtf8, toUtf8 } from "@aws-sdk/util-utf8-node"; + +/** + * Successful compilation indicates the client can be initialized + * with maximal configuration. + */ +export const initializeWithMaximalConfiguration = () => { + const defaultsMode = resolveDefaultsModeConfig({}); + const defaultConfigProvider = () => defaultsMode().then(loadConfigsForDefaultMode); + + const s3 = new S3Client({ + endpoint: "endpoint", + customUserAgent: "client-api-test-user-agent", + apiVersion: "2006-03-01", + base64Decoder: fromBase64, + base64Encoder: toBase64, + disableHostPrefix: false, + endpointProvider: () => null as unknown as EndpointV2, + logger: { + trace() {}, + debug() {}, + info() {}, + warn() {}, + error() {}, + }, + serviceId: "S3", + signerConstructor: SignatureV4MultiRegion, + signingEscapePath: false, + urlParser: parseUrl, + runtime: "node", + defaultsMode, + bodyLengthChecker: calculateBodyLength, + credentialDefaultProvider: decorateDefaultCredentialProvider(credentialDefaultProvider), + defaultUserAgentProvider: defaultUserAgent({ serviceId: "S3", clientVersion: "3.0.0-client-s3-interface-test" }), + eventStreamSerdeProvider: eventStreamSerdeProvider, + getAwsChunkedEncodingStream: getAwsChunkedEncodingStream, + maxAttempts: loadNodeConfig(NODE_MAX_ATTEMPT_CONFIG_OPTIONS), + md5: Hash.bind(null, "md5"), + region: loadNodeConfig(NODE_REGION_CONFIG_OPTIONS, NODE_REGION_CONFIG_FILE_OPTIONS), + requestHandler: new RequestHandler(defaultConfigProvider), + retryMode: loadNodeConfig({ + ...NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || DEFAULT_RETRY_MODE, + }), + sdkStreamMixin: sdkStreamMixin, + sha1: Hash.bind(null, "sha1"), + sha256: Hash.bind(null, "sha256"), + streamCollector: streamCollector, + streamHasher: streamHasher, + useArnRegion: loadNodeConfig(NODE_USE_ARN_REGION_CONFIG_OPTIONS), + useDualstackEndpoint: loadNodeConfig(NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS), + useFipsEndpoint: loadNodeConfig(NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS), + utf8Decoder: fromUtf8, + utf8Encoder: toUtf8, + }); + + return s3; +}; diff --git a/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMinimalConfiguration.ts b/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMinimalConfiguration.ts new file mode 100644 index 000000000000..e52262bcfde4 --- /dev/null +++ b/private/client-api-test/src/client-interface-tests/client-s3/impl/initializeWithMinimalConfiguration.ts @@ -0,0 +1,9 @@ +import { S3Client } from "@aws-sdk/client-s3"; + +/** + * Successful compilation indicates the client can be initialized + * with minimal configuration. + */ +export const initializeWithMinimalConfiguration = () => { + return new S3Client({}); +}; diff --git a/private/client-api-test/tsconfig.cjs.json b/private/client-api-test/tsconfig.cjs.json new file mode 100644 index 000000000000..3567d85ba846 --- /dev/null +++ b/private/client-api-test/tsconfig.cjs.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "outDir": "dist-cjs" + } +} diff --git a/private/client-api-test/tsconfig.es.json b/private/client-api-test/tsconfig.es.json new file mode 100644 index 000000000000..809f57bde65e --- /dev/null +++ b/private/client-api-test/tsconfig.es.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "lib": ["dom"], + "module": "esnext", + "outDir": "dist-es" + } +} diff --git a/private/client-api-test/tsconfig.json b/private/client-api-test/tsconfig.json new file mode 100644 index 000000000000..344909de2128 --- /dev/null +++ b/private/client-api-test/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "@tsconfig/node14/tsconfig.json", + "compilerOptions": { + "downlevelIteration": true, + "importHelpers": true, + "incremental": true, + "removeComments": true, + "resolveJsonModule": true, + "rootDir": "src", + "useUnknownInCatchVariables": false + }, + "exclude": ["test/"] +} diff --git a/private/client-api-test/tsconfig.types.json b/private/client-api-test/tsconfig.types.json new file mode 100644 index 000000000000..4c3dfa7b3d25 --- /dev/null +++ b/private/client-api-test/tsconfig.types.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "removeComments": false, + "declaration": true, + "declarationDir": "dist-types", + "emitDeclarationOnly": true + }, + "exclude": ["test/**/*", "dist-types/**/*"] +} diff --git a/private/client-api-test/typedoc.json b/private/client-api-test/typedoc.json new file mode 100644 index 000000000000..1b5cb0146719 --- /dev/null +++ b/private/client-api-test/typedoc.json @@ -0,0 +1,3 @@ +{ + "extends": "../../typedoc.client.json" +}