From bed09e3f45ad2ba1c1da51f72afcff651097ad0f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:58:16 +0000 Subject: [PATCH 1/7] Initial plan From 8cafed4e49c4207821167fe5c5e103a82667dd44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 01:06:50 +0000 Subject: [PATCH 2/7] fix(emitter-framework): use Record extends instead of additionalProperties for record models Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- ...-additional-properties-2026-3-4-0-58-57.md | 7 +++++++ .../components/interface-declaration.tsx | 21 +++---------------- .../components/interface-declaration.test.tsx | 18 +++++----------- 3 files changed, 15 insertions(+), 31 deletions(-) create mode 100644 .chronus/changes/copilot-fix-emit-additional-properties-2026-3-4-0-58-57.md diff --git a/.chronus/changes/copilot-fix-emit-additional-properties-2026-3-4-0-58-57.md b/.chronus/changes/copilot-fix-emit-additional-properties-2026-3-4-0-58-57.md new file mode 100644 index 00000000000..c748ba1d38b --- /dev/null +++ b/.chronus/changes/copilot-fix-emit-additional-properties-2026-3-4-0-58-57.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@typespec/emitter-framework" +--- + +Use `Record` extends instead of `additionalProperties` property for models that are or extend record types diff --git a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx index cb1cc107919..d92d28c0bb5 100644 --- a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx +++ b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx @@ -14,6 +14,7 @@ import { useTsp } from "../../core/context/tsp-context.js"; import { reportDiagnostic } from "../../lib.js"; import { declarationRefkeys, efRefkey } from "../utils/refkey.js"; import { InterfaceMember } from "./interface-member.js"; +import { RecordExpression } from "./record-expression.js"; import { TypeExpression } from "./type-expression.jsx"; export interface TypedInterfaceDeclarationProps extends Omit { type: Model | Interface; @@ -90,9 +91,7 @@ function getExtendsType($: Typekit, type: Model | Interface): Children | undefin if ($.array.is(type.baseModel)) { extending.push(); } else if ($.record.is(type.baseModel)) { - // Here we are in the additional properties land. - // Instead of extending we need to create an envelope property - // do nothing here. + extending.push(); } else { extending.push(efRefkey(type.baseModel)); } @@ -100,11 +99,8 @@ function getExtendsType($: Typekit, type: Model | Interface): Children | undefin const indexType = $.model.getIndexType(type); if (indexType) { - // When extending a record we need to override the element type to be unknown to avoid type errors if ($.record.is(indexType)) { - // Here we are in the additional properties land. - // Instead of extending we need to create an envelope property - // do nothing here. + extending.push(); } else { extending.push(); } @@ -129,17 +125,6 @@ function InterfaceBody(props: TypedInterfaceDeclarationProps): Children { let typeMembers: RekeyableMap | undefined; if ($.model.is(props.type)) { typeMembers = $.model.getProperties(props.type); - const additionalProperties = $.model.getAdditionalPropertiesRecord(props.type); - if (additionalProperties) { - typeMembers.set( - "additionalProperties", - $.modelProperty.create({ - name: "additionalProperties", - optional: true, - type: additionalProperties, - }), - ); - } } else { typeMembers = createRekeyableMap(props.type.operations); } diff --git a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx index 7d350ed434d..a617243f438 100644 --- a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx +++ b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx @@ -187,9 +187,8 @@ describe("Typescript Interface", () => { , ).toRenderTo(` - export interface DifferentSpreadModelRecord { + export interface DifferentSpreadModelRecord extends Record { knownProp: string; - additionalProperties?: Record; } `); }); @@ -235,9 +234,7 @@ describe("Typescript Interface", () => { , ).toRenderTo(` - export interface Foo { - additionalProperties?: Record; - }`); + export interface Foo extends Record {}`); }); it("creates an interface of a model that spreads a Record", async () => { @@ -261,9 +258,7 @@ describe("Typescript Interface", () => { , ).toRenderTo(` - export interface Foo { - additionalProperties?: Record; - } + export interface Foo extends Record {} `); }); @@ -300,13 +295,11 @@ describe("Typescript Interface", () => { export interface ModelForRecord { state: string; } - export interface DifferentSpreadModelRecord { + export interface DifferentSpreadModelRecord extends Record { knownProp: string; - additionalProperties?: Record; } export interface DifferentSpreadModelDerived extends DifferentSpreadModelRecord { derivedProp: ModelForRecord; - additionalProperties?: Record; }`); }); @@ -332,11 +325,10 @@ describe("Typescript Interface", () => { , ).toRenderTo(` - export interface Widget { + export interface Widget extends Record { id: string; weight: number; color: "blue" | "red"; - additionalProperties?: Record; }`); }); From 4742306a83ac01d0fe24fafa434380cb1ad5e529 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 20:59:15 +0000 Subject: [PATCH 3/7] fix(http-client-js): update test snapshots for Record extends pattern Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../additional-properties/extends.md | 3 +- .../scenarios/additional-properties/is.md | 5 ++- .../scenarios/additional-properties/spread.md | 3 +- .../test/scenarios/auth/basic_auth.md | 6 ++- .../test/scenarios/auth/bearer.md | 6 ++- .../test/scenarios/auth/client_structure.md | 6 ++- .../test/scenarios/auth/key_credential.md | 6 ++- .../scenarios/auth/sub_client_override.md | 6 ++- .../test/scenarios/client/global_namespace.md | 10 ++++- .../client/multiple_top_level_clients.md | 7 +++- .../test/scenarios/client/nested_client.md | 7 +++- .../scenarios/encoding/bytes_json_property.md | 5 ++- .../test/scenarios/encoding/bytes_nullable.md | 13 ++++-- .../encoding/model_with_bytes_property.md | 14 +++++-- .../http-operations/basic-request.md | 5 ++- .../http-operations/basic-response.md | 35 ++++++++++++---- .../test/scenarios/http-operations/basic.md | 10 ++++- .../http-operations/constant-header.md | 10 ++++- .../http-operations/optional-request-body.md | 9 +++- .../test/scenarios/http-operations/paging.md | 42 +++++++++++++++---- .../http-operations/with-parameters.md | 8 +++- .../models/inheritance_2_discriminators.md | 29 +++++++++---- .../models/inheritance_discriminator.md | 4 +- .../models/model_additional_properties.md | 3 +- .../test/scenarios/multipart/file.md | 6 ++- .../scenarios/multipart/file_content_type.md | 12 ++++-- .../constant_as_optional.md | 10 ++++- .../default_value_as_optional.md | 10 ++++- .../operation-parameters/no_parameters.md | 10 ++++- .../operation-parameters/only_optional.md | 5 ++- .../operation-parameters/only_required.md | 11 ++++- .../operation-parameters/union_body.md | 4 +- .../test/scenarios/serializers/arrays.md | 18 ++++++-- .../serializers/discriminated_union.md | 12 ++++-- .../serializers/discriminated_union_spread.md | 12 ++++-- .../test/scenarios/serializers/multipart.md | 4 +- .../property_references_property.md | 8 +++- .../test/scenarios/serializers/spread.md | 4 +- .../test/scenarios/server/default_url.md | 4 +- .../scenarios/server/multiple-parameters.md | 25 ++++++----- .../scenarios/server/parametrized-endpoint.md | 20 +++++---- 41 files changed, 327 insertions(+), 100 deletions(-) diff --git a/packages/http-client-js/test/scenarios/additional-properties/extends.md b/packages/http-client-js/test/scenarios/additional-properties/extends.md index 93ad1e93915..f9b45861f64 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/extends.md +++ b/packages/http-client-js/test/scenarios/additional-properties/extends.md @@ -20,11 +20,10 @@ op foo(): Widget; Should generate a model with name `Widget` with the known properties in the root and an evelop property called `additionalProperties` ```ts src/models/models.ts interface Widget -export interface Widget { +export interface Widget extends Record { name: string; age: number; optional?: string; - additionalProperties?: Record; } ``` diff --git a/packages/http-client-js/test/scenarios/additional-properties/is.md b/packages/http-client-js/test/scenarios/additional-properties/is.md index b1ebf098998..de72c0cb51b 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/is.md +++ b/packages/http-client-js/test/scenarios/additional-properties/is.md @@ -34,7 +34,10 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonRecordStringToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/additional-properties/spread.md b/packages/http-client-js/test/scenarios/additional-properties/spread.md index 963e5108cc4..387bb80f68c 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/spread.md +++ b/packages/http-client-js/test/scenarios/additional-properties/spread.md @@ -21,11 +21,10 @@ op foo(): Widget; Should generate a model with name `Widget` with the known properties in the root and an evelop property called `additionalProperties` ```ts src/models/models.ts interface Widget -export interface Widget { +export interface Widget extends Record { name: string; age: number; optional?: string; - additionalProperties?: Record; } ``` diff --git a/packages/http-client-js/test/scenarios/auth/basic_auth.md b/packages/http-client-js/test/scenarios/auth/basic_auth.md index 8da8fb1dae9..d015e19d2ae 100644 --- a/packages/http-client-js/test/scenarios/auth/basic_auth.md +++ b/packages/http-client-js/test/scenarios/auth/basic_auth.md @@ -25,7 +25,11 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { + constructor( + endpoint: string, + credential: BasicCredential, + options?: TestClientOptions, + ) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/bearer.md b/packages/http-client-js/test/scenarios/auth/bearer.md index 85a5fe5acdd..6740ae781c3 100644 --- a/packages/http-client-js/test/scenarios/auth/bearer.md +++ b/packages/http-client-js/test/scenarios/auth/bearer.md @@ -25,7 +25,11 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { + constructor( + endpoint: string, + credential: BasicCredential, + options?: TestClientOptions, + ) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/client_structure.md b/packages/http-client-js/test/scenarios/auth/client_structure.md index e52bdc143c9..ed83a7c56b3 100644 --- a/packages/http-client-js/test/scenarios/auth/client_structure.md +++ b/packages/http-client-js/test/scenarios/auth/client_structure.md @@ -27,7 +27,11 @@ export class MyApiClient { #context: MyApiClientContext; fooClient: FooClient; barClient: BarClient; - constructor(endpoint: string, credential: BasicCredential, options?: MyApiClientOptions) { + constructor( + endpoint: string, + credential: BasicCredential, + options?: MyApiClientOptions, + ) { this.#context = createMyApiClientContext(endpoint, credential, options); this.fooClient = new FooClient(endpoint, credential, options); this.barClient = new BarClient(endpoint, credential, options); diff --git a/packages/http-client-js/test/scenarios/auth/key_credential.md b/packages/http-client-js/test/scenarios/auth/key_credential.md index df9bfae4f77..9402479b87e 100644 --- a/packages/http-client-js/test/scenarios/auth/key_credential.md +++ b/packages/http-client-js/test/scenarios/auth/key_credential.md @@ -25,7 +25,11 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor(endpoint: string, credential: ApiKeyCredential, options?: TestClientOptions) { + constructor( + endpoint: string, + credential: ApiKeyCredential, + options?: TestClientOptions, + ) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/sub_client_override.md b/packages/http-client-js/test/scenarios/auth/sub_client_override.md index 52aba4b8632..15e0d1b5790 100644 --- a/packages/http-client-js/test/scenarios/auth/sub_client_override.md +++ b/packages/http-client-js/test/scenarios/auth/sub_client_override.md @@ -34,7 +34,11 @@ The subclient is not a child of the TestClient because they have different param ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { + constructor( + endpoint: string, + credential: BasicCredential, + options?: TestClientOptions, + ) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/client/global_namespace.md b/packages/http-client-js/test/scenarios/client/global_namespace.md index 48257ec6a84..50900efb1c5 100644 --- a/packages/http-client-js/test/scenarios/client/global_namespace.md +++ b/packages/http-client-js/test/scenarios/client/global_namespace.md @@ -17,7 +17,10 @@ export interface ClientContext extends Client {} ``` ```ts src/api/clientContext.ts function createClientContext -export function createClientContext(endpoint: string, options?: ClientOptions): ClientContext { +export function createClientContext( + endpoint: string, + options?: ClientOptions, +): ClientContext { const params: Record = { endpoint: endpoint, }; @@ -51,7 +54,10 @@ export class Client { It should generate an operation for foo ```ts src/api/clientOperations.ts function foo -export async function foo(client: ClientContext, options?: FooOptions): Promise { +export async function foo( + client: ClientContext, + options?: FooOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, diff --git a/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md b/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md index f33492f9597..7563d6d55b4 100644 --- a/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md +++ b/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md @@ -54,7 +54,12 @@ import { type BarClientOptions, createBarClientContext, } from "./api/barClientContext.js"; -import { create, type CreateOptions, get, type GetOptions } from "./api/barClientOperations.js"; +import { + create, + type CreateOptions, + get, + type GetOptions, +} from "./api/barClientOperations.js"; import type { BarItem } from "./models/models.js"; export class BarClient { diff --git a/packages/http-client-js/test/scenarios/client/nested_client.md b/packages/http-client-js/test/scenarios/client/nested_client.md index e7fdcaf3505..8c8271937b7 100644 --- a/packages/http-client-js/test/scenarios/client/nested_client.md +++ b/packages/http-client-js/test/scenarios/client/nested_client.md @@ -89,7 +89,12 @@ export class WidgetsClient { async create(weight: number, color: "red" | "blue", options?: CreateOptions) { return create(this.#context, weight, color, options); } - async update(id: string, weight: number, color: "red" | "blue", options?: UpdateOptions) { + async update( + id: string, + weight: number, + color: "red" | "blue", + options?: UpdateOptions, + ) { return update(this.#context, id, weight, color, options); } async delete_(id: string, options?: DeleteOptions) { diff --git a/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md b/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md index 9126c88a523..1e50db521ac 100644 --- a/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md +++ b/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md @@ -34,7 +34,10 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonBytesBodyToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md b/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md index aefb9c055da..6c75f19c38a 100644 --- a/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md +++ b/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md @@ -35,7 +35,10 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonModelWithBytesToApplicationTransform(response.body)!; } throw createRestError(response); @@ -47,7 +50,9 @@ export async function get( Should decode as uint8array the nullableProperty ```ts src/models/internal/serializers.ts function jsonModelWithBytesToApplicationTransform -export function jsonModelWithBytesToApplicationTransform(input_?: any): ModelWithBytes { +export function jsonModelWithBytesToApplicationTransform( + input_?: any, +): ModelWithBytes { if (!input_) { return input_ as any; } @@ -127,7 +132,9 @@ export async function post( Should encode as base64 the nullableProperty ```ts src/models/internal/serializers.ts function jsonModelWithBytesToTransportTransform -export function jsonModelWithBytesToTransportTransform(input_?: ModelWithBytes | null): any { +export function jsonModelWithBytesToTransportTransform( + input_?: ModelWithBytes | null, +): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md b/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md index ff4753fb5e1..1a0a7aa8852 100644 --- a/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md +++ b/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md @@ -16,7 +16,10 @@ model BytesProperty { ## TypeScript ```ts src/api/testClientOperations.ts function get -export async function get(client: TestClientContext, options?: GetOptions): Promise { +export async function get( + client: TestClientContext, + options?: GetOptions, +): Promise { const path = parse("/bytes").expand({}); const httpRequestOptions = { headers: {}, @@ -26,7 +29,10 @@ export async function get(client: TestClientContext, options?: GetOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonBytesPropertyToApplicationTransform(response.body)!; } throw createRestError(response); @@ -34,7 +40,9 @@ export async function get(client: TestClientContext, options?: GetOptions): Prom ``` ```ts src/models/internal/serializers.ts function jsonBytesPropertyToApplicationTransform -export function jsonBytesPropertyToApplicationTransform(input_?: any): BytesProperty { +export function jsonBytesPropertyToApplicationTransform( + input_?: any, +): BytesProperty { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/http-operations/basic-request.md b/packages/http-client-js/test/scenarios/http-operations/basic-request.md index 939accf720b..b2675349636 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic-request.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic-request.md @@ -20,7 +20,10 @@ interface Widgets { ### Request ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { +export async function read( + client: WidgetsClientContext, + options?: ReadOptions, +): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, diff --git a/packages/http-client-js/test/scenarios/http-operations/basic-response.md b/packages/http-client-js/test/scenarios/http-operations/basic-response.md index 8c1e29a339f..9c67fbd93e2 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic-response.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic-response.md @@ -20,7 +20,10 @@ interface Widgets { ### **Response Handling** ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { +export async function read( + client: WidgetsClientContext, + options?: ReadOptions, +): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -85,7 +88,10 @@ export function jsonWidgetToApplicationTransform(input_?: any): Widget { The function reads a `Widget` instance from the response body, ensuring it only processes JSON responses with a `200` status. ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { +export async function read( + client: WidgetsClientContext, + options?: ReadOptions, +): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -95,7 +101,10 @@ export async function read(client: WidgetsClientContext, options?: ReadOptions): if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); @@ -147,7 +156,10 @@ export async function read( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonWidgetToApplicationTransform(response.body)!; } if (+response.status === 204 && !response.body) { @@ -198,7 +210,10 @@ This function ensures that the response is correctly processed based on its `con TODO: need to implement xml serialization ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { +export async function read( + client: WidgetsClientContext, + options?: ReadOptions, +): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -208,10 +223,16 @@ export async function read(client: WidgetsClientContext, options?: ReadOptions): if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonWidgetToApplicationTransform(response.body)!; } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/xml")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/xml") + ) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/basic.md b/packages/http-client-js/test/scenarios/http-operations/basic.md index 5ba7ab7591a..af0c864e82b 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic.md @@ -110,7 +110,10 @@ A function named `foo` is generated to handle the HTTP request. It prepares the - If the response status code is unexpected, an exception is thrown. ```ts src/api/testClientOperations.ts function foo -export async function foo(client: TestClientContext, options?: FooOptions): Promise { +export async function foo( + client: TestClientContext, + options?: FooOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -120,7 +123,10 @@ export async function foo(client: TestClientContext, options?: FooOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/constant-header.md b/packages/http-client-js/test/scenarios/http-operations/constant-header.md index ea3235dc883..b44ca09074e 100644 --- a/packages/http-client-js/test/scenarios/http-operations/constant-header.md +++ b/packages/http-client-js/test/scenarios/http-operations/constant-header.md @@ -13,7 +13,10 @@ model Foo { ## Operation ```ts src/api/testClientOperations.ts function foo -export async function foo(client: TestClientContext, options?: FooOptions): Promise { +export async function foo( + client: TestClientContext, + options?: FooOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -25,7 +28,10 @@ export async function foo(client: TestClientContext, options?: FooOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonFooToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md b/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md index eae992db4e7..600422ce8aa 100644 --- a/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md +++ b/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md @@ -18,7 +18,10 @@ op omit(@body body?: BodyModel): NoContentResponse; ## Operations ```ts src/api/testClientOperations.ts function set -export async function set(client: TestClientContext, options?: SetOptions): Promise { +export async function set( + client: TestClientContext, + options?: SetOptions, +): Promise { const path = parse("/set").expand({}); const httpRequestOptions = { headers: {}, @@ -39,7 +42,9 @@ export async function set(client: TestClientContext, options?: SetOptions): Prom ## Transform ```ts src/models/internal/serializers.ts function jsonBodyModelToTransportTransform -export function jsonBodyModelToTransportTransform(input_?: BodyModel | null): any { +export function jsonBodyModelToTransportTransform( + input_?: BodyModel | null, +): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/http-operations/paging.md b/packages/http-client-js/test/scenarios/http-operations/paging.md index 4d763b04685..64e5d18245d 100644 --- a/packages/http-client-js/test/scenarios/http-operations/paging.md +++ b/packages/http-client-js/test/scenarios/http-operations/paging.md @@ -29,7 +29,10 @@ export function link( function getElements(response: LinkPageResponse) { return response.pets; } - async function getPagedResponse(nextToken?: string, settings?: LinkPageSettings) { + async function getPagedResponse( + nextToken?: string, + settings?: LinkPageSettings, + ) { const combinedOptions = { ...options, ...settings }; if (nextToken) { @@ -50,7 +53,11 @@ export function link( ``` ```ts src/api/testClientOperations.ts function linkSend -async function linkSend(client: TestClientContext, filter: string, options?: Record) { +async function linkSend( + client: TestClientContext, + filter: string, + options?: Record, +) { const path = parse("/link{?filter,nextToken}").expand({ filter: filter, ...(options?.nextToken && { nextToken: options.nextToken }), @@ -63,11 +70,17 @@ async function linkSend(client: TestClientContext, filter: string, options?: Rec ``` ```ts src/api/testClientOperations.ts function linkDeserialize -function linkDeserialize(response: PathUncheckedResponse, options?: LinkOptions) { +function linkDeserialize( + response: PathUncheckedResponse, + options?: LinkOptions, +) { if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return { pets: jsonArrayPetToApplicationTransform(response.body.pets), }!; @@ -150,7 +163,10 @@ export function link( function getElements(response: LinkPageResponse) { return response.pets; } - async function getPagedResponse(nextToken?: string, settings?: LinkPageSettings) { + async function getPagedResponse( + nextToken?: string, + settings?: LinkPageSettings, + ) { let response: PathUncheckedResponse; if (nextToken) { response = await client.pathUnchecked(nextToken).get(); @@ -171,7 +187,11 @@ export function link( ``` ```ts src/api/testClientOperations.ts function linkSend -async function linkSend(client: TestClientContext, filter: string, options?: Record) { +async function linkSend( + client: TestClientContext, + filter: string, + options?: Record, +) { const path = parse("/link{?filter,maxPageSize}").expand({ filter: filter, ...(options?.maxPageSize && { maxPageSize: options.maxPageSize }), @@ -184,11 +204,17 @@ async function linkSend(client: TestClientContext, filter: string, options?: Rec ``` ```ts src/api/testClientOperations.ts function linkDeserialize -function linkDeserialize(response: PathUncheckedResponse, options?: LinkOptions) { +function linkDeserialize( + response: PathUncheckedResponse, + options?: LinkOptions, +) { if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return { pets: jsonArrayPetToApplicationTransform(response.body.pets), link: response.body.link, diff --git a/packages/http-client-js/test/scenarios/http-operations/with-parameters.md b/packages/http-client-js/test/scenarios/http-operations/with-parameters.md index b9fd5d5daa3..f1d8e0eadbf 100644 --- a/packages/http-client-js/test/scenarios/http-operations/with-parameters.md +++ b/packages/http-client-js/test/scenarios/http-operations/with-parameters.md @@ -71,7 +71,13 @@ export class WidgetsClient { constructor(endpoint: string, options?: WidgetsClientOptions) { this.#context = createWidgetsClientContext(endpoint, options); } - async read(id: string, etag: string, foo: string, name: string, options?: ReadOptions) { + async read( + id: string, + etag: string, + foo: string, + name: string, + options?: ReadOptions, + ) { return read(this.#context, id, etag, foo, name, options); } } diff --git a/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md b/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md index d1e4ca3e1a5..f72c979df1f 100644 --- a/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md +++ b/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md @@ -50,7 +50,10 @@ export async function getModel( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonFishToApplicationTransform(response.body)!; } throw createRestError(response); @@ -225,7 +228,9 @@ export function jsonSharkToApplicationTransform(input_?: any): Shark { age: input_.age, }!; } -export function jsonSawSharkToTransportTransform(input_?: SawShark | null): any { +export function jsonSawSharkToTransportTransform( + input_?: SawShark | null, +): any { if (!input_) { return input_ as any; } @@ -245,7 +250,9 @@ export function jsonSawSharkToApplicationTransform(input_?: any): SawShark { age: input_.age, }!; } -export function jsonGoblinSharkToTransportTransform(input_?: GoblinShark | null): any { +export function jsonGoblinSharkToTransportTransform( + input_?: GoblinShark | null, +): any { if (!input_) { return input_ as any; } @@ -255,7 +262,9 @@ export function jsonGoblinSharkToTransportTransform(input_?: GoblinShark | null) age: input_.age, }!; } -export function jsonGoblinSharkToApplicationTransform(input_?: any): GoblinShark { +export function jsonGoblinSharkToApplicationTransform( + input_?: any, +): GoblinShark { if (!input_) { return input_ as any; } @@ -289,7 +298,9 @@ export function jsonSalmonToApplicationTransform(input_?: any): Salmon { age: input_.age, }!; } -export function jsonArrayFishToTransportTransform(items_?: Array | null): any { +export function jsonArrayFishToTransportTransform( + items_?: Array | null, +): any { if (!items_) { return items_ as any; } @@ -315,7 +326,9 @@ export function jsonArrayFishToApplicationTransform(items_?: any): Array { return _transformedArray as any; } -export function jsonRecordFishToTransportTransform(items_?: Record | null): any { +export function jsonRecordFishToTransportTransform( + items_?: Record | null, +): any { if (!items_) { return items_ as any; } @@ -329,7 +342,9 @@ export function jsonRecordFishToTransportTransform(items_?: Record return _transformedRecord; } -export function jsonRecordFishToApplicationTransform(items_?: any): Record { +export function jsonRecordFishToApplicationTransform( + items_?: any, +): Record { if (!items_) { return items_ as any; } diff --git a/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md b/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md index 4455db63c7e..7225032e141 100644 --- a/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md +++ b/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md @@ -36,7 +36,9 @@ export interface TRex extends Dinosaur { ## Serializer ```ts src/models/internal/serializers.ts function jsonDinosaurToTransportTransform -export function jsonDinosaurToTransportTransform(input_?: Dinosaur | null): any { +export function jsonDinosaurToTransportTransform( + input_?: Dinosaur | null, +): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/models/model_additional_properties.md b/packages/http-client-js/test/scenarios/models/model_additional_properties.md index 924b99e456c..cd2c28b4d04 100644 --- a/packages/http-client-js/test/scenarios/models/model_additional_properties.md +++ b/packages/http-client-js/test/scenarios/models/model_additional_properties.md @@ -32,11 +32,10 @@ export interface ExtraFeature { ``` ```ts src/models/models.ts interface Dog -export interface Dog { +export interface Dog extends Record { id: string; name: string; color: "black" | "brown"; - additionalProperties?: Record; } ``` diff --git a/packages/http-client-js/test/scenarios/multipart/file.md b/packages/http-client-js/test/scenarios/multipart/file.md index 05f8e6deb45..91b63d16bf0 100644 --- a/packages/http-client-js/test/scenarios/multipart/file.md +++ b/packages/http-client-js/test/scenarios/multipart/file.md @@ -139,7 +139,11 @@ export async function doThing( headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [...bodyParam.files.map((files: any) => createFilePartDescriptor("files", files))], + body: [ + ...bodyParam.files.map((files: any) => + createFilePartDescriptor("files", files), + ), + ], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/multipart/file_content_type.md b/packages/http-client-js/test/scenarios/multipart/file_content_type.md index e0b16a553a7..cfe6aa3fb9b 100644 --- a/packages/http-client-js/test/scenarios/multipart/file_content_type.md +++ b/packages/http-client-js/test/scenarios/multipart/file_content_type.md @@ -27,12 +27,16 @@ export async function imageJpegContentType( body: FileWithHttpPartSpecificContentTypeRequest, options?: ImageJpegContentTypeOptions, ): Promise { - const path = parse("/check-filename-and-specific-content-type-with-httppart").expand({}); + const path = parse( + "/check-filename-and-specific-content-type-with-httppart", + ).expand({}); const httpRequestOptions = { headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [createFilePartDescriptor("profileImage", body.profileImage, "image/jpg")], + body: [ + createFilePartDescriptor("profileImage", body.profileImage, "image/jpg"), + ], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); @@ -56,7 +60,9 @@ export function jsonFileWithHttpPartSpecificContentTypeRequestToApplicationTrans return input_ as any; } return { - profileImage: jsonFileSpecificContentTypeToApplicationTransform(input_.profileImage), + profileImage: jsonFileSpecificContentTypeToApplicationTransform( + input_.profileImage, + ), }!; } ``` diff --git a/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md index 6fbcd3786f6..16cf54431c8 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md @@ -12,7 +12,10 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get(client: TestClientContext, options?: GetOptions): Promise { +export async function get( + client: TestClientContext, + options?: GetOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -24,7 +27,10 @@ export async function get(client: TestClientContext, options?: GetOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md index ce338a13366..66b7467f026 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md @@ -12,7 +12,10 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get(client: TestClientContext, options?: GetOptions): Promise { +export async function get( + client: TestClientContext, + options?: GetOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -24,7 +27,10 @@ export async function get(client: TestClientContext, options?: GetOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md b/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md index a3397119395..6cded1ac6fd 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md @@ -12,7 +12,10 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get(client: TestClientContext, options?: GetOptions): Promise { +export async function get( + client: TestClientContext, + options?: GetOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -22,7 +25,10 @@ export async function get(client: TestClientContext, options?: GetOptions): Prom if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md index 3f5410bc972..7cc5302fdec 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md @@ -29,7 +29,10 @@ export async function getWithParams( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/only_required.md b/packages/http-client-js/test/scenarios/operation-parameters/only_required.md index 28e21c83cd9..99fdcca5040 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/only_required.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/only_required.md @@ -30,7 +30,10 @@ export async function getWithParams( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return response.body!; } throw createRestError(response); @@ -51,7 +54,11 @@ export class TestClient { constructor(endpoint: string, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, options); } - async getWithParams(name: string, age: number, options?: GetWithParamsOptions) { + async getWithParams( + name: string, + age: number, + options?: GetWithParamsOptions, + ) { return getWithParams(this.#context, name, age, options); } } diff --git a/packages/http-client-js/test/scenarios/operation-parameters/union_body.md b/packages/http-client-js/test/scenarios/operation-parameters/union_body.md index 725af219159..f6fd3e7ccba 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/union_body.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/union_body.md @@ -74,7 +74,9 @@ export class TestClient { ``` ```ts src/models/internal/serializers.ts function jsonEnumsOnlyCasesToTransportTransform -export function jsonEnumsOnlyCasesToTransportTransform(input_?: EnumsOnlyCases | null): any { +export function jsonEnumsOnlyCasesToTransportTransform( + input_?: EnumsOnlyCases | null, +): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/arrays.md b/packages/http-client-js/test/scenarios/serializers/arrays.md index 81fbe295b4b..9cf39cda4d0 100644 --- a/packages/http-client-js/test/scenarios/serializers/arrays.md +++ b/packages/http-client-js/test/scenarios/serializers/arrays.md @@ -36,7 +36,9 @@ export interface Foo { The generated transformation functions iterate over `int32[]` values, but since **no actual transformation occurs**, this code could be **optimized away**. ```ts src/models/internal/serializers.ts function jsonArrayInt32ToTransportTransform -export function jsonArrayInt32ToTransportTransform(items_?: Array | null): any { +export function jsonArrayInt32ToTransportTransform( + items_?: Array | null, +): any { if (!items_) { return items_ as any; } @@ -71,7 +73,10 @@ export function jsonFooToTransportTransform(input_?: Foo | null): any { Handles the API request, expecting a `Widget` response and applying the correct deserialization function. ```ts src/api/clientOperations.ts function foo -export async function foo(client: ClientContext, options?: FooOptions): Promise { +export async function foo( + client: ClientContext, + options?: FooOptions, +): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -81,7 +86,10 @@ export async function foo(client: ClientContext, options?: FooOptions): Promise< if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { + if ( + +response.status === 200 && + response.headers["content-type"]?.includes("application/json") + ) { return jsonFooToApplicationTransform(response.body)!; } throw createRestError(response); @@ -93,7 +101,9 @@ export async function foo(client: ClientContext, options?: FooOptions): Promise< Again, the transformation logic is redundant for primitive types. Instead of generating a function, the deserializer could **use the array directly**. ```ts src/models/internal/serializers.ts function jsonArrayInt32ToApplicationTransform -export function jsonArrayInt32ToApplicationTransform(items_?: any): Array { +export function jsonArrayInt32ToApplicationTransform( + items_?: any, +): Array { if (!items_) { return items_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union.md index 733531cc722..f7e48eb8d28 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union.md @@ -32,7 +32,9 @@ op put(@body body: WidgetData): void; ## Typescript ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportTransform -export function jsonWidgetDataToTransportTransform(input_?: WidgetData | null): any { +export function jsonWidgetDataToTransportTransform( + input_?: WidgetData | null, +): any { if (!input_) { return input_ as any; } @@ -50,7 +52,9 @@ export function jsonWidgetDataToApplicationTransform(input_?: any): WidgetData { ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportDiscriminator -export function jsonWidgetDataToTransportDiscriminator(input_?: WidgetData): any { +export function jsonWidgetDataToTransportDiscriminator( + input_?: WidgetData, +): any { if (!input_) { return input_ as any; } @@ -68,7 +72,9 @@ export function jsonWidgetDataToTransportDiscriminator(input_?: WidgetData): any ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToApplicationDiscriminator -export function jsonWidgetDataToApplicationDiscriminator(input_?: any): WidgetData { +export function jsonWidgetDataToApplicationDiscriminator( + input_?: any, +): WidgetData { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md index d3207af88a1..7d786bff39f 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md @@ -70,7 +70,9 @@ export function jsonSpreadRecordForDiscriminatedUnionToApplicationTransform( ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportTransform -export function jsonWidgetDataToTransportTransform(input_?: WidgetData | null): any { +export function jsonWidgetDataToTransportTransform( + input_?: WidgetData | null, +): any { if (!input_) { return input_ as any; } @@ -79,7 +81,9 @@ export function jsonWidgetDataToTransportTransform(input_?: WidgetData | null): ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToApplicationDiscriminator -export function jsonWidgetDataToApplicationDiscriminator(input_?: any): WidgetData { +export function jsonWidgetDataToApplicationDiscriminator( + input_?: any, +): WidgetData { if (!input_) { return input_ as any; } @@ -97,7 +101,9 @@ export function jsonWidgetDataToApplicationDiscriminator(input_?: any): WidgetDa ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportDiscriminator -export function jsonWidgetDataToTransportDiscriminator(input_?: WidgetData): any { +export function jsonWidgetDataToTransportDiscriminator( + input_?: WidgetData, +): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/multipart.md b/packages/http-client-js/test/scenarios/serializers/multipart.md index 282ae711c2f..e8f1228e3be 100644 --- a/packages/http-client-js/test/scenarios/serializers/multipart.md +++ b/packages/http-client-js/test/scenarios/serializers/multipart.md @@ -47,7 +47,9 @@ export async function create( headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [createFilePartDescriptor("profileImage", body.profileImage, "image/jpg")], + body: [ + createFilePartDescriptor("profileImage", body.profileImage, "image/jpg"), + ], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/serializers/property_references_property.md b/packages/http-client-js/test/scenarios/serializers/property_references_property.md index 3a569985f49..658082394e7 100644 --- a/packages/http-client-js/test/scenarios/serializers/property_references_property.md +++ b/packages/http-client-js/test/scenarios/serializers/property_references_property.md @@ -44,7 +44,9 @@ Validates that the serializer generates the correct serialization logic for: - Nullable property references (`assignedTo?: TodoItem.assignedTo | null`) ```ts src/models/internal/serializers.ts function jsonTodoItemPatchToTransportTransform -export function jsonTodoItemPatchToTransportTransform(input_?: TodoItemPatch | null): any { +export function jsonTodoItemPatchToTransportTransform( + input_?: TodoItemPatch | null, +): any { if (!input_) { return input_ as any; } @@ -60,7 +62,9 @@ export function jsonTodoItemPatchToTransportTransform(input_?: TodoItemPatch | n Validates the deserialization logic maintains type consistency when converting from transport to application models. ```ts src/models/internal/serializers.ts function jsonTodoItemPatchToApplicationTransform -export function jsonTodoItemPatchToApplicationTransform(input_?: any): TodoItemPatch { +export function jsonTodoItemPatchToApplicationTransform( + input_?: any, +): TodoItemPatch { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/spread.md b/packages/http-client-js/test/scenarios/serializers/spread.md index a954b013d0a..d7a9add0273 100644 --- a/packages/http-client-js/test/scenarios/serializers/spread.md +++ b/packages/http-client-js/test/scenarios/serializers/spread.md @@ -53,7 +53,9 @@ export async function spreadWithMultipleParameters( requiredString: requiredString, optionalInt: options?.optionalInt, requiredIntList: jsonArrayInt32ToTransportTransform(requiredIntList), - optionalStringList: jsonArrayStringToTransportTransform(options?.optionalStringList), + optionalStringList: jsonArrayStringToTransportTransform( + options?.optionalStringList, + ), }, }; const response = await client.pathUnchecked(path).put(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/server/default_url.md b/packages/http-client-js/test/scenarios/server/default_url.md index 9e467ee39c1..4d4dcfe843b 100644 --- a/packages/http-client-js/test/scenarios/server/default_url.md +++ b/packages/http-client-js/test/scenarios/server/default_url.md @@ -17,7 +17,9 @@ op foo(): void; The client uses the optional endpoint if available or the default endpoint ```ts src/api/testClientContext.ts function createTestClientContext -export function createTestClientContext(options?: TestClientOptions): TestClientContext { +export function createTestClientContext( + options?: TestClientOptions, +): TestClientContext { const params: Record = { endpoint: options?.endpoint ?? "https://example.org/api", }; diff --git a/packages/http-client-js/test/scenarios/server/multiple-parameters.md b/packages/http-client-js/test/scenarios/server/multiple-parameters.md index 672b30d7303..8c9038a17ac 100644 --- a/packages/http-client-js/test/scenarios/server/multiple-parameters.md +++ b/packages/http-client-js/test/scenarios/server/multiple-parameters.md @@ -24,7 +24,11 @@ op noOperationParams(): NoContentResponse; The client context should use the parameters to build the baseUrl using the template. ```ts src/api/testClientContext.ts -import { type Client, type ClientOptions, getClient } from "@typespec/ts-http-runtime"; +import { + type Client, + type ClientOptions, + getClient, +} from "@typespec/ts-http-runtime"; export interface TestClientContext extends Client {} export interface TestClientOptions extends ClientOptions { @@ -39,15 +43,16 @@ export function createTestClientContext( endpoint: endpoint, apiVersion: apiVersion, }; - const resolvedEndpoint = "{endpoint}/server/path/multiple/{apiVersion}".replace( - /{([^}]+)}/g, - (_, key) => - key in params - ? String(params[key]) - : (() => { - throw new Error(`Missing parameter: ${key}`); - })(), - ); + const resolvedEndpoint = + "{endpoint}/server/path/multiple/{apiVersion}".replace( + /{([^}]+)}/g, + (_, key) => + key in params + ? String(params[key]) + : (() => { + throw new Error(`Missing parameter: ${key}`); + })(), + ); return getClient(resolvedEndpoint, { ...options, }); diff --git a/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md b/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md index fb7a449b24a..063696b8718 100644 --- a/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md +++ b/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md @@ -24,7 +24,11 @@ op noOperationParams(): NoContentResponse; The client context should use the parameters to build the baseUrl using the template. ```ts src/api/testClientContext.ts -import { type Client, type ClientOptions, getClient } from "@typespec/ts-http-runtime"; +import { + type Client, + type ClientOptions, + getClient, +} from "@typespec/ts-http-runtime"; export interface TestClientContext extends Client {} export interface TestClientOptions extends ClientOptions { @@ -37,12 +41,14 @@ export function createTestClientContext( const params: Record = { foo: foo, }; - const resolvedEndpoint = "{foo}/server/path/multiple".replace(/{([^}]+)}/g, (_, key) => - key in params - ? String(params[key]) - : (() => { - throw new Error(`Missing parameter: ${key}`); - })(), + const resolvedEndpoint = "{foo}/server/path/multiple".replace( + /{([^}]+)}/g, + (_, key) => + key in params + ? String(params[key]) + : (() => { + throw new Error(`Missing parameter: ${key}`); + })(), ); return getClient(resolvedEndpoint, { ...options, From 39eb57b3aff9287c32ec1206334cadfac8d48055 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 21:33:40 +0000 Subject: [PATCH 4/7] chore: merge latest main and fix formatting Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../scenarios/additional-properties/is.md | 5 +-- .../test/scenarios/auth/basic_auth.md | 6 +-- .../test/scenarios/auth/bearer.md | 6 +-- .../test/scenarios/auth/client_structure.md | 6 +-- .../test/scenarios/auth/key_credential.md | 6 +-- .../scenarios/auth/sub_client_override.md | 6 +-- .../test/scenarios/client/global_namespace.md | 10 +---- .../client/multiple_top_level_clients.md | 7 +--- .../test/scenarios/client/nested_client.md | 7 +--- .../scenarios/encoding/bytes_json_property.md | 5 +-- .../test/scenarios/encoding/bytes_nullable.md | 13 ++---- .../encoding/model_with_bytes_property.md | 14 ++----- .../http-operations/basic-request.md | 5 +-- .../http-operations/basic-response.md | 35 ++++------------ .../test/scenarios/http-operations/basic.md | 10 +---- .../http-operations/constant-header.md | 10 +---- .../http-operations/optional-request-body.md | 9 +--- .../test/scenarios/http-operations/paging.md | 42 ++++--------------- .../http-operations/with-parameters.md | 8 +--- .../models/inheritance_2_discriminators.md | 29 ++++--------- .../models/inheritance_discriminator.md | 4 +- .../test/scenarios/multipart/file.md | 6 +-- .../scenarios/multipart/file_content_type.md | 12 ++---- .../constant_as_optional.md | 10 +---- .../default_value_as_optional.md | 10 +---- .../operation-parameters/no_parameters.md | 10 +---- .../operation-parameters/only_optional.md | 5 +-- .../operation-parameters/only_required.md | 11 +---- .../operation-parameters/union_body.md | 4 +- .../test/scenarios/serializers/arrays.md | 18 ++------ .../serializers/discriminated_union.md | 12 ++---- .../serializers/discriminated_union_spread.md | 12 ++---- .../test/scenarios/serializers/multipart.md | 4 +- .../property_references_property.md | 8 +--- .../test/scenarios/serializers/spread.md | 4 +- .../test/scenarios/server/default_url.md | 4 +- .../scenarios/server/multiple-parameters.md | 25 +++++------ .../scenarios/server/parametrized-endpoint.md | 20 ++++----- 38 files changed, 94 insertions(+), 324 deletions(-) diff --git a/packages/http-client-js/test/scenarios/additional-properties/is.md b/packages/http-client-js/test/scenarios/additional-properties/is.md index de72c0cb51b..b1ebf098998 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/is.md +++ b/packages/http-client-js/test/scenarios/additional-properties/is.md @@ -34,10 +34,7 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonRecordStringToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/auth/basic_auth.md b/packages/http-client-js/test/scenarios/auth/basic_auth.md index d015e19d2ae..8da8fb1dae9 100644 --- a/packages/http-client-js/test/scenarios/auth/basic_auth.md +++ b/packages/http-client-js/test/scenarios/auth/basic_auth.md @@ -25,11 +25,7 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor( - endpoint: string, - credential: BasicCredential, - options?: TestClientOptions, - ) { + constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/bearer.md b/packages/http-client-js/test/scenarios/auth/bearer.md index 6740ae781c3..85a5fe5acdd 100644 --- a/packages/http-client-js/test/scenarios/auth/bearer.md +++ b/packages/http-client-js/test/scenarios/auth/bearer.md @@ -25,11 +25,7 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor( - endpoint: string, - credential: BasicCredential, - options?: TestClientOptions, - ) { + constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/client_structure.md b/packages/http-client-js/test/scenarios/auth/client_structure.md index ed83a7c56b3..e52bdc143c9 100644 --- a/packages/http-client-js/test/scenarios/auth/client_structure.md +++ b/packages/http-client-js/test/scenarios/auth/client_structure.md @@ -27,11 +27,7 @@ export class MyApiClient { #context: MyApiClientContext; fooClient: FooClient; barClient: BarClient; - constructor( - endpoint: string, - credential: BasicCredential, - options?: MyApiClientOptions, - ) { + constructor(endpoint: string, credential: BasicCredential, options?: MyApiClientOptions) { this.#context = createMyApiClientContext(endpoint, credential, options); this.fooClient = new FooClient(endpoint, credential, options); this.barClient = new BarClient(endpoint, credential, options); diff --git a/packages/http-client-js/test/scenarios/auth/key_credential.md b/packages/http-client-js/test/scenarios/auth/key_credential.md index 9402479b87e..df9bfae4f77 100644 --- a/packages/http-client-js/test/scenarios/auth/key_credential.md +++ b/packages/http-client-js/test/scenarios/auth/key_credential.md @@ -25,11 +25,7 @@ The client signature should include a positional parameter for credential of typ ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor( - endpoint: string, - credential: ApiKeyCredential, - options?: TestClientOptions, - ) { + constructor(endpoint: string, credential: ApiKeyCredential, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/auth/sub_client_override.md b/packages/http-client-js/test/scenarios/auth/sub_client_override.md index 15e0d1b5790..52aba4b8632 100644 --- a/packages/http-client-js/test/scenarios/auth/sub_client_override.md +++ b/packages/http-client-js/test/scenarios/auth/sub_client_override.md @@ -34,11 +34,7 @@ The subclient is not a child of the TestClient because they have different param ```ts src/testClient.ts class TestClient export class TestClient { #context: TestClientContext; - constructor( - endpoint: string, - credential: BasicCredential, - options?: TestClientOptions, - ) { + constructor(endpoint: string, credential: BasicCredential, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, credential, options); } async valid(options?: ValidOptions) { diff --git a/packages/http-client-js/test/scenarios/client/global_namespace.md b/packages/http-client-js/test/scenarios/client/global_namespace.md index 50900efb1c5..48257ec6a84 100644 --- a/packages/http-client-js/test/scenarios/client/global_namespace.md +++ b/packages/http-client-js/test/scenarios/client/global_namespace.md @@ -17,10 +17,7 @@ export interface ClientContext extends Client {} ``` ```ts src/api/clientContext.ts function createClientContext -export function createClientContext( - endpoint: string, - options?: ClientOptions, -): ClientContext { +export function createClientContext(endpoint: string, options?: ClientOptions): ClientContext { const params: Record = { endpoint: endpoint, }; @@ -54,10 +51,7 @@ export class Client { It should generate an operation for foo ```ts src/api/clientOperations.ts function foo -export async function foo( - client: ClientContext, - options?: FooOptions, -): Promise { +export async function foo(client: ClientContext, options?: FooOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, diff --git a/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md b/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md index 7563d6d55b4..f33492f9597 100644 --- a/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md +++ b/packages/http-client-js/test/scenarios/client/multiple_top_level_clients.md @@ -54,12 +54,7 @@ import { type BarClientOptions, createBarClientContext, } from "./api/barClientContext.js"; -import { - create, - type CreateOptions, - get, - type GetOptions, -} from "./api/barClientOperations.js"; +import { create, type CreateOptions, get, type GetOptions } from "./api/barClientOperations.js"; import type { BarItem } from "./models/models.js"; export class BarClient { diff --git a/packages/http-client-js/test/scenarios/client/nested_client.md b/packages/http-client-js/test/scenarios/client/nested_client.md index 8c8271937b7..e7fdcaf3505 100644 --- a/packages/http-client-js/test/scenarios/client/nested_client.md +++ b/packages/http-client-js/test/scenarios/client/nested_client.md @@ -89,12 +89,7 @@ export class WidgetsClient { async create(weight: number, color: "red" | "blue", options?: CreateOptions) { return create(this.#context, weight, color, options); } - async update( - id: string, - weight: number, - color: "red" | "blue", - options?: UpdateOptions, - ) { + async update(id: string, weight: number, color: "red" | "blue", options?: UpdateOptions) { return update(this.#context, id, weight, color, options); } async delete_(id: string, options?: DeleteOptions) { diff --git a/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md b/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md index 1e50db521ac..9126c88a523 100644 --- a/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md +++ b/packages/http-client-js/test/scenarios/encoding/bytes_json_property.md @@ -34,10 +34,7 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonBytesBodyToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md b/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md index 6c75f19c38a..aefb9c055da 100644 --- a/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md +++ b/packages/http-client-js/test/scenarios/encoding/bytes_nullable.md @@ -35,10 +35,7 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonModelWithBytesToApplicationTransform(response.body)!; } throw createRestError(response); @@ -50,9 +47,7 @@ export async function get( Should decode as uint8array the nullableProperty ```ts src/models/internal/serializers.ts function jsonModelWithBytesToApplicationTransform -export function jsonModelWithBytesToApplicationTransform( - input_?: any, -): ModelWithBytes { +export function jsonModelWithBytesToApplicationTransform(input_?: any): ModelWithBytes { if (!input_) { return input_ as any; } @@ -132,9 +127,7 @@ export async function post( Should encode as base64 the nullableProperty ```ts src/models/internal/serializers.ts function jsonModelWithBytesToTransportTransform -export function jsonModelWithBytesToTransportTransform( - input_?: ModelWithBytes | null, -): any { +export function jsonModelWithBytesToTransportTransform(input_?: ModelWithBytes | null): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md b/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md index 1a0a7aa8852..ff4753fb5e1 100644 --- a/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md +++ b/packages/http-client-js/test/scenarios/encoding/model_with_bytes_property.md @@ -16,10 +16,7 @@ model BytesProperty { ## TypeScript ```ts src/api/testClientOperations.ts function get -export async function get( - client: TestClientContext, - options?: GetOptions, -): Promise { +export async function get(client: TestClientContext, options?: GetOptions): Promise { const path = parse("/bytes").expand({}); const httpRequestOptions = { headers: {}, @@ -29,10 +26,7 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonBytesPropertyToApplicationTransform(response.body)!; } throw createRestError(response); @@ -40,9 +34,7 @@ export async function get( ``` ```ts src/models/internal/serializers.ts function jsonBytesPropertyToApplicationTransform -export function jsonBytesPropertyToApplicationTransform( - input_?: any, -): BytesProperty { +export function jsonBytesPropertyToApplicationTransform(input_?: any): BytesProperty { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/http-operations/basic-request.md b/packages/http-client-js/test/scenarios/http-operations/basic-request.md index b2675349636..939accf720b 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic-request.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic-request.md @@ -20,10 +20,7 @@ interface Widgets { ### Request ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read( - client: WidgetsClientContext, - options?: ReadOptions, -): Promise { +export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, diff --git a/packages/http-client-js/test/scenarios/http-operations/basic-response.md b/packages/http-client-js/test/scenarios/http-operations/basic-response.md index 9c67fbd93e2..8c1e29a339f 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic-response.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic-response.md @@ -20,10 +20,7 @@ interface Widgets { ### **Response Handling** ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read( - client: WidgetsClientContext, - options?: ReadOptions, -): Promise { +export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -88,10 +85,7 @@ export function jsonWidgetToApplicationTransform(input_?: any): Widget { The function reads a `Widget` instance from the response body, ensuring it only processes JSON responses with a `200` status. ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read( - client: WidgetsClientContext, - options?: ReadOptions, -): Promise { +export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -101,10 +95,7 @@ export async function read( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); @@ -156,10 +147,7 @@ export async function read( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonWidgetToApplicationTransform(response.body)!; } if (+response.status === 204 && !response.body) { @@ -210,10 +198,7 @@ This function ensures that the response is correctly processed based on its `con TODO: need to implement xml serialization ```ts src/api/widgetsClient/widgetsClientOperations.ts function read -export async function read( - client: WidgetsClientContext, - options?: ReadOptions, -): Promise { +export async function read(client: WidgetsClientContext, options?: ReadOptions): Promise { const path = parse("/widgets").expand({}); const httpRequestOptions = { headers: {}, @@ -223,16 +208,10 @@ export async function read( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonWidgetToApplicationTransform(response.body)!; } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/xml") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/xml")) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/basic.md b/packages/http-client-js/test/scenarios/http-operations/basic.md index af0c864e82b..5ba7ab7591a 100644 --- a/packages/http-client-js/test/scenarios/http-operations/basic.md +++ b/packages/http-client-js/test/scenarios/http-operations/basic.md @@ -110,10 +110,7 @@ A function named `foo` is generated to handle the HTTP request. It prepares the - If the response status code is unexpected, an exception is thrown. ```ts src/api/testClientOperations.ts function foo -export async function foo( - client: TestClientContext, - options?: FooOptions, -): Promise { +export async function foo(client: TestClientContext, options?: FooOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -123,10 +120,7 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonWidgetToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/constant-header.md b/packages/http-client-js/test/scenarios/http-operations/constant-header.md index b44ca09074e..ea3235dc883 100644 --- a/packages/http-client-js/test/scenarios/http-operations/constant-header.md +++ b/packages/http-client-js/test/scenarios/http-operations/constant-header.md @@ -13,10 +13,7 @@ model Foo { ## Operation ```ts src/api/testClientOperations.ts function foo -export async function foo( - client: TestClientContext, - options?: FooOptions, -): Promise { +export async function foo(client: TestClientContext, options?: FooOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -28,10 +25,7 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonFooToApplicationTransform(response.body)!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md b/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md index 600422ce8aa..eae992db4e7 100644 --- a/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md +++ b/packages/http-client-js/test/scenarios/http-operations/optional-request-body.md @@ -18,10 +18,7 @@ op omit(@body body?: BodyModel): NoContentResponse; ## Operations ```ts src/api/testClientOperations.ts function set -export async function set( - client: TestClientContext, - options?: SetOptions, -): Promise { +export async function set(client: TestClientContext, options?: SetOptions): Promise { const path = parse("/set").expand({}); const httpRequestOptions = { headers: {}, @@ -42,9 +39,7 @@ export async function set( ## Transform ```ts src/models/internal/serializers.ts function jsonBodyModelToTransportTransform -export function jsonBodyModelToTransportTransform( - input_?: BodyModel | null, -): any { +export function jsonBodyModelToTransportTransform(input_?: BodyModel | null): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/http-operations/paging.md b/packages/http-client-js/test/scenarios/http-operations/paging.md index 64e5d18245d..4d763b04685 100644 --- a/packages/http-client-js/test/scenarios/http-operations/paging.md +++ b/packages/http-client-js/test/scenarios/http-operations/paging.md @@ -29,10 +29,7 @@ export function link( function getElements(response: LinkPageResponse) { return response.pets; } - async function getPagedResponse( - nextToken?: string, - settings?: LinkPageSettings, - ) { + async function getPagedResponse(nextToken?: string, settings?: LinkPageSettings) { const combinedOptions = { ...options, ...settings }; if (nextToken) { @@ -53,11 +50,7 @@ export function link( ``` ```ts src/api/testClientOperations.ts function linkSend -async function linkSend( - client: TestClientContext, - filter: string, - options?: Record, -) { +async function linkSend(client: TestClientContext, filter: string, options?: Record) { const path = parse("/link{?filter,nextToken}").expand({ filter: filter, ...(options?.nextToken && { nextToken: options.nextToken }), @@ -70,17 +63,11 @@ async function linkSend( ``` ```ts src/api/testClientOperations.ts function linkDeserialize -function linkDeserialize( - response: PathUncheckedResponse, - options?: LinkOptions, -) { +function linkDeserialize(response: PathUncheckedResponse, options?: LinkOptions) { if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return { pets: jsonArrayPetToApplicationTransform(response.body.pets), }!; @@ -163,10 +150,7 @@ export function link( function getElements(response: LinkPageResponse) { return response.pets; } - async function getPagedResponse( - nextToken?: string, - settings?: LinkPageSettings, - ) { + async function getPagedResponse(nextToken?: string, settings?: LinkPageSettings) { let response: PathUncheckedResponse; if (nextToken) { response = await client.pathUnchecked(nextToken).get(); @@ -187,11 +171,7 @@ export function link( ``` ```ts src/api/testClientOperations.ts function linkSend -async function linkSend( - client: TestClientContext, - filter: string, - options?: Record, -) { +async function linkSend(client: TestClientContext, filter: string, options?: Record) { const path = parse("/link{?filter,maxPageSize}").expand({ filter: filter, ...(options?.maxPageSize && { maxPageSize: options.maxPageSize }), @@ -204,17 +184,11 @@ async function linkSend( ``` ```ts src/api/testClientOperations.ts function linkDeserialize -function linkDeserialize( - response: PathUncheckedResponse, - options?: LinkOptions, -) { +function linkDeserialize(response: PathUncheckedResponse, options?: LinkOptions) { if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return { pets: jsonArrayPetToApplicationTransform(response.body.pets), link: response.body.link, diff --git a/packages/http-client-js/test/scenarios/http-operations/with-parameters.md b/packages/http-client-js/test/scenarios/http-operations/with-parameters.md index f1d8e0eadbf..b9fd5d5daa3 100644 --- a/packages/http-client-js/test/scenarios/http-operations/with-parameters.md +++ b/packages/http-client-js/test/scenarios/http-operations/with-parameters.md @@ -71,13 +71,7 @@ export class WidgetsClient { constructor(endpoint: string, options?: WidgetsClientOptions) { this.#context = createWidgetsClientContext(endpoint, options); } - async read( - id: string, - etag: string, - foo: string, - name: string, - options?: ReadOptions, - ) { + async read(id: string, etag: string, foo: string, name: string, options?: ReadOptions) { return read(this.#context, id, etag, foo, name, options); } } diff --git a/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md b/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md index f72c979df1f..d1e4ca3e1a5 100644 --- a/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md +++ b/packages/http-client-js/test/scenarios/models/inheritance_2_discriminators.md @@ -50,10 +50,7 @@ export async function getModel( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonFishToApplicationTransform(response.body)!; } throw createRestError(response); @@ -228,9 +225,7 @@ export function jsonSharkToApplicationTransform(input_?: any): Shark { age: input_.age, }!; } -export function jsonSawSharkToTransportTransform( - input_?: SawShark | null, -): any { +export function jsonSawSharkToTransportTransform(input_?: SawShark | null): any { if (!input_) { return input_ as any; } @@ -250,9 +245,7 @@ export function jsonSawSharkToApplicationTransform(input_?: any): SawShark { age: input_.age, }!; } -export function jsonGoblinSharkToTransportTransform( - input_?: GoblinShark | null, -): any { +export function jsonGoblinSharkToTransportTransform(input_?: GoblinShark | null): any { if (!input_) { return input_ as any; } @@ -262,9 +255,7 @@ export function jsonGoblinSharkToTransportTransform( age: input_.age, }!; } -export function jsonGoblinSharkToApplicationTransform( - input_?: any, -): GoblinShark { +export function jsonGoblinSharkToApplicationTransform(input_?: any): GoblinShark { if (!input_) { return input_ as any; } @@ -298,9 +289,7 @@ export function jsonSalmonToApplicationTransform(input_?: any): Salmon { age: input_.age, }!; } -export function jsonArrayFishToTransportTransform( - items_?: Array | null, -): any { +export function jsonArrayFishToTransportTransform(items_?: Array | null): any { if (!items_) { return items_ as any; } @@ -326,9 +315,7 @@ export function jsonArrayFishToApplicationTransform(items_?: any): Array { return _transformedArray as any; } -export function jsonRecordFishToTransportTransform( - items_?: Record | null, -): any { +export function jsonRecordFishToTransportTransform(items_?: Record | null): any { if (!items_) { return items_ as any; } @@ -342,9 +329,7 @@ export function jsonRecordFishToTransportTransform( return _transformedRecord; } -export function jsonRecordFishToApplicationTransform( - items_?: any, -): Record { +export function jsonRecordFishToApplicationTransform(items_?: any): Record { if (!items_) { return items_ as any; } diff --git a/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md b/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md index 7225032e141..4455db63c7e 100644 --- a/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md +++ b/packages/http-client-js/test/scenarios/models/inheritance_discriminator.md @@ -36,9 +36,7 @@ export interface TRex extends Dinosaur { ## Serializer ```ts src/models/internal/serializers.ts function jsonDinosaurToTransportTransform -export function jsonDinosaurToTransportTransform( - input_?: Dinosaur | null, -): any { +export function jsonDinosaurToTransportTransform(input_?: Dinosaur | null): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/multipart/file.md b/packages/http-client-js/test/scenarios/multipart/file.md index 91b63d16bf0..05f8e6deb45 100644 --- a/packages/http-client-js/test/scenarios/multipart/file.md +++ b/packages/http-client-js/test/scenarios/multipart/file.md @@ -139,11 +139,7 @@ export async function doThing( headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [ - ...bodyParam.files.map((files: any) => - createFilePartDescriptor("files", files), - ), - ], + body: [...bodyParam.files.map((files: any) => createFilePartDescriptor("files", files))], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/multipart/file_content_type.md b/packages/http-client-js/test/scenarios/multipart/file_content_type.md index cfe6aa3fb9b..e0b16a553a7 100644 --- a/packages/http-client-js/test/scenarios/multipart/file_content_type.md +++ b/packages/http-client-js/test/scenarios/multipart/file_content_type.md @@ -27,16 +27,12 @@ export async function imageJpegContentType( body: FileWithHttpPartSpecificContentTypeRequest, options?: ImageJpegContentTypeOptions, ): Promise { - const path = parse( - "/check-filename-and-specific-content-type-with-httppart", - ).expand({}); + const path = parse("/check-filename-and-specific-content-type-with-httppart").expand({}); const httpRequestOptions = { headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [ - createFilePartDescriptor("profileImage", body.profileImage, "image/jpg"), - ], + body: [createFilePartDescriptor("profileImage", body.profileImage, "image/jpg")], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); @@ -60,9 +56,7 @@ export function jsonFileWithHttpPartSpecificContentTypeRequestToApplicationTrans return input_ as any; } return { - profileImage: jsonFileSpecificContentTypeToApplicationTransform( - input_.profileImage, - ), + profileImage: jsonFileSpecificContentTypeToApplicationTransform(input_.profileImage), }!; } ``` diff --git a/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md index 16cf54431c8..6fbcd3786f6 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/constant_as_optional.md @@ -12,10 +12,7 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get( - client: TestClientContext, - options?: GetOptions, -): Promise { +export async function get(client: TestClientContext, options?: GetOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -27,10 +24,7 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md index 66b7467f026..ce338a13366 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/default_value_as_optional.md @@ -12,10 +12,7 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get( - client: TestClientContext, - options?: GetOptions, -): Promise { +export async function get(client: TestClientContext, options?: GetOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: { @@ -27,10 +24,7 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md b/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md index 6cded1ac6fd..a3397119395 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/no_parameters.md @@ -12,10 +12,7 @@ namespace Test; Even when there are no parameters defined in the spec, it will have an optional options bag which contains operation options. ```ts src/api/testClientOperations.ts function get -export async function get( - client: TestClientContext, - options?: GetOptions, -): Promise { +export async function get(client: TestClientContext, options?: GetOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -25,10 +22,7 @@ export async function get( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md b/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md index 7cc5302fdec..3f5410bc972 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/only_optional.md @@ -29,10 +29,7 @@ export async function getWithParams( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return response.body!; } throw createRestError(response); diff --git a/packages/http-client-js/test/scenarios/operation-parameters/only_required.md b/packages/http-client-js/test/scenarios/operation-parameters/only_required.md index 99fdcca5040..28e21c83cd9 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/only_required.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/only_required.md @@ -30,10 +30,7 @@ export async function getWithParams( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return response.body!; } throw createRestError(response); @@ -54,11 +51,7 @@ export class TestClient { constructor(endpoint: string, options?: TestClientOptions) { this.#context = createTestClientContext(endpoint, options); } - async getWithParams( - name: string, - age: number, - options?: GetWithParamsOptions, - ) { + async getWithParams(name: string, age: number, options?: GetWithParamsOptions) { return getWithParams(this.#context, name, age, options); } } diff --git a/packages/http-client-js/test/scenarios/operation-parameters/union_body.md b/packages/http-client-js/test/scenarios/operation-parameters/union_body.md index f6fd3e7ccba..725af219159 100644 --- a/packages/http-client-js/test/scenarios/operation-parameters/union_body.md +++ b/packages/http-client-js/test/scenarios/operation-parameters/union_body.md @@ -74,9 +74,7 @@ export class TestClient { ``` ```ts src/models/internal/serializers.ts function jsonEnumsOnlyCasesToTransportTransform -export function jsonEnumsOnlyCasesToTransportTransform( - input_?: EnumsOnlyCases | null, -): any { +export function jsonEnumsOnlyCasesToTransportTransform(input_?: EnumsOnlyCases | null): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/arrays.md b/packages/http-client-js/test/scenarios/serializers/arrays.md index 9cf39cda4d0..81fbe295b4b 100644 --- a/packages/http-client-js/test/scenarios/serializers/arrays.md +++ b/packages/http-client-js/test/scenarios/serializers/arrays.md @@ -36,9 +36,7 @@ export interface Foo { The generated transformation functions iterate over `int32[]` values, but since **no actual transformation occurs**, this code could be **optimized away**. ```ts src/models/internal/serializers.ts function jsonArrayInt32ToTransportTransform -export function jsonArrayInt32ToTransportTransform( - items_?: Array | null, -): any { +export function jsonArrayInt32ToTransportTransform(items_?: Array | null): any { if (!items_) { return items_ as any; } @@ -73,10 +71,7 @@ export function jsonFooToTransportTransform(input_?: Foo | null): any { Handles the API request, expecting a `Widget` response and applying the correct deserialization function. ```ts src/api/clientOperations.ts function foo -export async function foo( - client: ClientContext, - options?: FooOptions, -): Promise { +export async function foo(client: ClientContext, options?: FooOptions): Promise { const path = parse("/").expand({}); const httpRequestOptions = { headers: {}, @@ -86,10 +81,7 @@ export async function foo( if (typeof options?.operationOptions?.onResponse === "function") { options?.operationOptions?.onResponse(response); } - if ( - +response.status === 200 && - response.headers["content-type"]?.includes("application/json") - ) { + if (+response.status === 200 && response.headers["content-type"]?.includes("application/json")) { return jsonFooToApplicationTransform(response.body)!; } throw createRestError(response); @@ -101,9 +93,7 @@ export async function foo( Again, the transformation logic is redundant for primitive types. Instead of generating a function, the deserializer could **use the array directly**. ```ts src/models/internal/serializers.ts function jsonArrayInt32ToApplicationTransform -export function jsonArrayInt32ToApplicationTransform( - items_?: any, -): Array { +export function jsonArrayInt32ToApplicationTransform(items_?: any): Array { if (!items_) { return items_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union.md index f7e48eb8d28..733531cc722 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union.md @@ -32,9 +32,7 @@ op put(@body body: WidgetData): void; ## Typescript ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportTransform -export function jsonWidgetDataToTransportTransform( - input_?: WidgetData | null, -): any { +export function jsonWidgetDataToTransportTransform(input_?: WidgetData | null): any { if (!input_) { return input_ as any; } @@ -52,9 +50,7 @@ export function jsonWidgetDataToApplicationTransform(input_?: any): WidgetData { ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportDiscriminator -export function jsonWidgetDataToTransportDiscriminator( - input_?: WidgetData, -): any { +export function jsonWidgetDataToTransportDiscriminator(input_?: WidgetData): any { if (!input_) { return input_ as any; } @@ -72,9 +68,7 @@ export function jsonWidgetDataToTransportDiscriminator( ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToApplicationDiscriminator -export function jsonWidgetDataToApplicationDiscriminator( - input_?: any, -): WidgetData { +export function jsonWidgetDataToApplicationDiscriminator(input_?: any): WidgetData { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md index 7d786bff39f..d3207af88a1 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md @@ -70,9 +70,7 @@ export function jsonSpreadRecordForDiscriminatedUnionToApplicationTransform( ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportTransform -export function jsonWidgetDataToTransportTransform( - input_?: WidgetData | null, -): any { +export function jsonWidgetDataToTransportTransform(input_?: WidgetData | null): any { if (!input_) { return input_ as any; } @@ -81,9 +79,7 @@ export function jsonWidgetDataToTransportTransform( ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToApplicationDiscriminator -export function jsonWidgetDataToApplicationDiscriminator( - input_?: any, -): WidgetData { +export function jsonWidgetDataToApplicationDiscriminator(input_?: any): WidgetData { if (!input_) { return input_ as any; } @@ -101,9 +97,7 @@ export function jsonWidgetDataToApplicationDiscriminator( ``` ```ts src/models/internal/serializers.ts function jsonWidgetDataToTransportDiscriminator -export function jsonWidgetDataToTransportDiscriminator( - input_?: WidgetData, -): any { +export function jsonWidgetDataToTransportDiscriminator(input_?: WidgetData): any { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/multipart.md b/packages/http-client-js/test/scenarios/serializers/multipart.md index e8f1228e3be..282ae711c2f 100644 --- a/packages/http-client-js/test/scenarios/serializers/multipart.md +++ b/packages/http-client-js/test/scenarios/serializers/multipart.md @@ -47,9 +47,7 @@ export async function create( headers: { "content-type": options?.contentType ?? "multipart/form-data", }, - body: [ - createFilePartDescriptor("profileImage", body.profileImage, "image/jpg"), - ], + body: [createFilePartDescriptor("profileImage", body.profileImage, "image/jpg")], }; const response = await client.pathUnchecked(path).post(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/serializers/property_references_property.md b/packages/http-client-js/test/scenarios/serializers/property_references_property.md index 658082394e7..3a569985f49 100644 --- a/packages/http-client-js/test/scenarios/serializers/property_references_property.md +++ b/packages/http-client-js/test/scenarios/serializers/property_references_property.md @@ -44,9 +44,7 @@ Validates that the serializer generates the correct serialization logic for: - Nullable property references (`assignedTo?: TodoItem.assignedTo | null`) ```ts src/models/internal/serializers.ts function jsonTodoItemPatchToTransportTransform -export function jsonTodoItemPatchToTransportTransform( - input_?: TodoItemPatch | null, -): any { +export function jsonTodoItemPatchToTransportTransform(input_?: TodoItemPatch | null): any { if (!input_) { return input_ as any; } @@ -62,9 +60,7 @@ export function jsonTodoItemPatchToTransportTransform( Validates the deserialization logic maintains type consistency when converting from transport to application models. ```ts src/models/internal/serializers.ts function jsonTodoItemPatchToApplicationTransform -export function jsonTodoItemPatchToApplicationTransform( - input_?: any, -): TodoItemPatch { +export function jsonTodoItemPatchToApplicationTransform(input_?: any): TodoItemPatch { if (!input_) { return input_ as any; } diff --git a/packages/http-client-js/test/scenarios/serializers/spread.md b/packages/http-client-js/test/scenarios/serializers/spread.md index d7a9add0273..a954b013d0a 100644 --- a/packages/http-client-js/test/scenarios/serializers/spread.md +++ b/packages/http-client-js/test/scenarios/serializers/spread.md @@ -53,9 +53,7 @@ export async function spreadWithMultipleParameters( requiredString: requiredString, optionalInt: options?.optionalInt, requiredIntList: jsonArrayInt32ToTransportTransform(requiredIntList), - optionalStringList: jsonArrayStringToTransportTransform( - options?.optionalStringList, - ), + optionalStringList: jsonArrayStringToTransportTransform(options?.optionalStringList), }, }; const response = await client.pathUnchecked(path).put(httpRequestOptions); diff --git a/packages/http-client-js/test/scenarios/server/default_url.md b/packages/http-client-js/test/scenarios/server/default_url.md index 4d4dcfe843b..9e467ee39c1 100644 --- a/packages/http-client-js/test/scenarios/server/default_url.md +++ b/packages/http-client-js/test/scenarios/server/default_url.md @@ -17,9 +17,7 @@ op foo(): void; The client uses the optional endpoint if available or the default endpoint ```ts src/api/testClientContext.ts function createTestClientContext -export function createTestClientContext( - options?: TestClientOptions, -): TestClientContext { +export function createTestClientContext(options?: TestClientOptions): TestClientContext { const params: Record = { endpoint: options?.endpoint ?? "https://example.org/api", }; diff --git a/packages/http-client-js/test/scenarios/server/multiple-parameters.md b/packages/http-client-js/test/scenarios/server/multiple-parameters.md index 8c9038a17ac..672b30d7303 100644 --- a/packages/http-client-js/test/scenarios/server/multiple-parameters.md +++ b/packages/http-client-js/test/scenarios/server/multiple-parameters.md @@ -24,11 +24,7 @@ op noOperationParams(): NoContentResponse; The client context should use the parameters to build the baseUrl using the template. ```ts src/api/testClientContext.ts -import { - type Client, - type ClientOptions, - getClient, -} from "@typespec/ts-http-runtime"; +import { type Client, type ClientOptions, getClient } from "@typespec/ts-http-runtime"; export interface TestClientContext extends Client {} export interface TestClientOptions extends ClientOptions { @@ -43,16 +39,15 @@ export function createTestClientContext( endpoint: endpoint, apiVersion: apiVersion, }; - const resolvedEndpoint = - "{endpoint}/server/path/multiple/{apiVersion}".replace( - /{([^}]+)}/g, - (_, key) => - key in params - ? String(params[key]) - : (() => { - throw new Error(`Missing parameter: ${key}`); - })(), - ); + const resolvedEndpoint = "{endpoint}/server/path/multiple/{apiVersion}".replace( + /{([^}]+)}/g, + (_, key) => + key in params + ? String(params[key]) + : (() => { + throw new Error(`Missing parameter: ${key}`); + })(), + ); return getClient(resolvedEndpoint, { ...options, }); diff --git a/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md b/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md index 063696b8718..fb7a449b24a 100644 --- a/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md +++ b/packages/http-client-js/test/scenarios/server/parametrized-endpoint.md @@ -24,11 +24,7 @@ op noOperationParams(): NoContentResponse; The client context should use the parameters to build the baseUrl using the template. ```ts src/api/testClientContext.ts -import { - type Client, - type ClientOptions, - getClient, -} from "@typespec/ts-http-runtime"; +import { type Client, type ClientOptions, getClient } from "@typespec/ts-http-runtime"; export interface TestClientContext extends Client {} export interface TestClientOptions extends ClientOptions { @@ -41,14 +37,12 @@ export function createTestClientContext( const params: Record = { foo: foo, }; - const resolvedEndpoint = "{foo}/server/path/multiple".replace( - /{([^}]+)}/g, - (_, key) => - key in params - ? String(params[key]) - : (() => { - throw new Error(`Missing parameter: ${key}`); - })(), + const resolvedEndpoint = "{foo}/server/path/multiple".replace(/{([^}]+)}/g, (_, key) => + key in params + ? String(params[key]) + : (() => { + throw new Error(`Missing parameter: ${key}`); + })(), ); return getClient(resolvedEndpoint, { ...options, From 9b066b1423dd20db34207fb2119883166633599c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:11:54 +0000 Subject: [PATCH 5/7] fix(http-client-js): fix e2e tests - spread additional properties directly instead of wrapping in additionalProperties Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../components/interface-declaration.tsx | 12 +- .../components/interface-declaration.test.tsx | 2 +- ...-model-additional-properties-transform.tsx | 40 ++--- .../additional-properties/main.test.ts | 72 ++++---- .../additional-properties/spreads.test.ts | 159 +++++++++--------- .../additional-properties/extends.md | 4 +- .../scenarios/additional-properties/spread.md | 8 +- .../models/model_additional_properties.md | 6 +- .../serializers/discriminated_union_spread.md | 6 +- 9 files changed, 153 insertions(+), 156 deletions(-) diff --git a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx index d92d28c0bb5..2dc97fd9517 100644 --- a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx +++ b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx @@ -100,7 +100,17 @@ function getExtendsType($: Typekit, type: Model | Interface): Children | undefin const indexType = $.model.getIndexType(type); if (indexType) { if ($.record.is(indexType)) { - extending.push(); + const elementType = indexType.indexer!.value; + // Only use extends Record if all known properties are assignable to T. + // When properties have incompatible types (e.g., id: number with Record), + // skip the extends clause to avoid TypeScript index signature conflicts. + const properties = $.model.getProperties(type); + const allCompatible = Array.from(properties.values()).every((prop) => + $.type.isAssignableTo(prop.type, elementType), + ); + if (allCompatible) { + extending.push(); + } } else { extending.push(); } diff --git a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx index a617243f438..a012a4d84c3 100644 --- a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx +++ b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx @@ -295,7 +295,7 @@ describe("Typescript Interface", () => { export interface ModelForRecord { state: string; } - export interface DifferentSpreadModelRecord extends Record { + export interface DifferentSpreadModelRecord { knownProp: string; } export interface DifferentSpreadModelDerived extends DifferentSpreadModelRecord { diff --git a/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx b/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx index a458d1b49a9..1ac38e645e1 100644 --- a/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx +++ b/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx @@ -1,5 +1,4 @@ import { Children, code, mapJoin } from "@alloy-js/core"; -import * as ts from "@alloy-js/typescript"; import type { Model } from "@typespec/compiler"; import { useTsp } from "@typespec/emitter-framework"; import { getJsonRecordTransformRefkey } from "./json-record-transform.jsx"; @@ -18,36 +17,23 @@ export function JsonAdditionalPropertiesTransform(props: JsonAdditionalPropertie return null; } - if (props.target === "application") { - const properties = $.model.getProperties(props.type, { includeExtended: true }); - const destructuredProperties = mapJoin( - () => properties, - (name) => name, - { - joiner: ",", - ender: ",", - }, - ); - - // Inline destructuring that extracts the properties and passes the rest to jsonRecordUnknownToApplicationTransform_2 - const inlineDestructure = code` - ${getJsonRecordTransformRefkey(additionalProperties, props.target)}( - (({ ${destructuredProperties} ...rest }) => rest)(${props.itemRef}) - ), - `; - - return ( - <> - {inlineDestructure} - - ); - } + const properties = $.model.getProperties(props.type, { includeExtended: true }); + const destructuredProperties = mapJoin( + () => properties, + (name) => name, + { + joiner: ",", + ender: ",", + }, + ); - const itemRef = code`${props.itemRef}.additionalProperties`; + // Extract additional properties by destructuring known properties and spreading the rest + const restExpr = code`(({ ${destructuredProperties} ...rest }) => rest)(${props.itemRef})`; + // Spread additional properties directly onto the object (not wrapped in additionalProperties) return ( <> - ...({getJsonRecordTransformRefkey(additionalProperties, props.target)}({itemRef}) ), + ...({getJsonRecordTransformRefkey(additionalProperties, props.target)}({restExpr}) ), ); } diff --git a/packages/http-client-js/test/e2e/http/type/property/additional-properties/main.test.ts b/packages/http-client-js/test/e2e/http/type/property/additional-properties/main.test.ts index f7cf77f74b7..e8574e31c30 100644 --- a/packages/http-client-js/test/e2e/http/type/property/additional-properties/main.test.ts +++ b/packages/http-client-js/test/e2e/http/type/property/additional-properties/main.test.ts @@ -20,18 +20,18 @@ describe("Type.Property.AdditionalProperties", () => { it("Expected response body: {'name': 'ExtendsUnknownAdditionalProperties', 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { const response = await client.get(); expect(response).toEqual({ - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, name: "ExtendsUnknownAdditionalProperties", + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'name': 'ExtendsUnknownAdditionalProperties', 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { await client.put({ - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, name: "ExtendsUnknownAdditionalProperties", + prop1: 32, + prop2: true, + prop3: "abc", }); }); }); @@ -46,14 +46,12 @@ describe("Type.Property.AdditionalProperties", () => { it("Expected response body: {'name': 'ExtendsUnknownAdditionalProperties', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { const response = await client.get(); expect(response).toEqual({ - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, name: "ExtendsUnknownAdditionalProperties", index: 314, age: 2.71875, + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'name': 'ExtendsUnknownAdditionalProperties', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { @@ -61,7 +59,9 @@ describe("Type.Property.AdditionalProperties", () => { name: "ExtendsUnknownAdditionalProperties", index: 314, age: 2.71875, - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); }); @@ -76,11 +76,13 @@ describe("Type.Property.AdditionalProperties", () => { it("Expected response body: {'kind': 'derived', 'name': 'Derived', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { const response = await client.get(); expect(response).toEqual({ - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, kind: "derived", name: "Derived", index: 314, age: 2.71875, + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'kind': 'derived', 'name': 'Derived', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { @@ -89,11 +91,9 @@ describe("Type.Property.AdditionalProperties", () => { age: 2.71875, kind: "derived", name: "Derived", - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, + prop1: 32, + prop2: true, + prop3: "abc", }; await client.put(input); }); @@ -105,18 +105,18 @@ describe("Type.Property.AdditionalProperties", () => { const response = await client.get(); expect(response).toEqual({ name: "IsUnknownAdditionalProperties", - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'name': 'IsUnknownAdditionalProperties', 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { await client.put({ name: "IsUnknownAdditionalProperties", - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); }); @@ -134,7 +134,9 @@ describe("Type.Property.AdditionalProperties", () => { name: "IsUnknownAdditionalProperties", index: 314, age: 2.71875, - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'name': 'IsUnknownAdditionalProperties', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { @@ -142,11 +144,9 @@ describe("Type.Property.AdditionalProperties", () => { name: "IsUnknownAdditionalProperties", index: 314, age: 2.71875, - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); }); @@ -165,7 +165,9 @@ describe("Type.Property.AdditionalProperties", () => { name: "Derived", index: 314, age: 2.71875, - additionalProperties: { prop1: 32, prop2: true, prop3: "abc" }, + prop1: 32, + prop2: true, + prop3: "abc", }); }); it("Expected input body: {'kind': 'derived', 'name': 'Derived', 'index': 314, 'age': 2.71875, 'prop1': 32, 'prop2': true, 'prop3': 'abc'}", async () => { @@ -174,11 +176,9 @@ describe("Type.Property.AdditionalProperties", () => { name: "Derived", index: 314, age: 2.71875, - additionalProperties: { - prop1: 32, - prop2: true, - prop3: "abc", - }, + prop1: 32, + prop2: true, + prop3: "abc", } as any); }); }); diff --git a/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts b/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts index a7c742a6c76..783b7314c59 100644 --- a/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts +++ b/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts @@ -4,13 +4,21 @@ import { ExtendsDifferentSpreadModelArrayClient, ExtendsDifferentSpreadModelClient, ExtendsDifferentSpreadStringClient, + ExtendsFloatAdditionalProperties, ExtendsFloatClient, + ExtendsModelAdditionalProperties, + ExtendsModelArrayAdditionalProperties, ExtendsModelArrayClient, ExtendsModelClient, + ExtendsStringAdditionalProperties, ExtendsStringClient, + IsFloatAdditionalProperties, IsFloatClient, + IsModelAdditionalProperties, + IsModelArrayAdditionalProperties, IsModelArrayClient, IsModelClient, + IsStringAdditionalProperties, IsStringClient, MultipleSpreadClient, SpreadDifferentFloatClient, @@ -18,16 +26,17 @@ import { SpreadDifferentModelClient, SpreadDifferentStringClient, SpreadFloatClient, + SpreadFloatRecord, SpreadModelArrayClient, + SpreadModelArrayRecord, SpreadModelClient, - SpreadRecordForNonDiscriminatedUnion, - SpreadRecordForNonDiscriminatedUnion2, - SpreadRecordForNonDiscriminatedUnion3, + SpreadModelRecord, SpreadRecordNonDiscriminatedUnion2Client, SpreadRecordNonDiscriminatedUnion3Client, SpreadRecordNonDiscriminatedUnionClient, SpreadRecordUnionClient, SpreadStringClient, + SpreadStringRecord, } from "../../../../generated/type/property/additional-properties/src/index.js"; // Helper to create a client instance with common options. @@ -39,9 +48,9 @@ const clientOptions = { describe("Missing AdditionalProperties Endpoints", () => { describe("ExtendsString", () => { const client = new ExtendsStringClient(clientOptions); - const expected = { - additionalProperties: { prop: "abc" }, + const expected: ExtendsStringAdditionalProperties = { name: "ExtendsStringAdditionalProperties", + prop: "abc", }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -54,9 +63,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("IsString", () => { const client = new IsStringClient({ allowInsecureConnection: true }); - const expected = { - additionalProperties: { prop: "abc" }, + const expected: IsStringAdditionalProperties = { name: "IsStringAdditionalProperties", + prop: "abc", }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -71,9 +80,9 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadStringClient({ allowInsecureConnection: true, }); - const expected = { - additionalProperties: { prop: "abc" }, + const expected: SpreadStringRecord = { name: "SpreadSpringRecord", + prop: "abc", }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -86,9 +95,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("ExtendsFloat", () => { const client = new ExtendsFloatClient(clientOptions); - const expected = { - additionalProperties: { prop: 43.125 }, + const expected: ExtendsFloatAdditionalProperties = { id: 43.125, + prop: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -101,9 +110,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("IsFloat", () => { const client = new IsFloatClient(clientOptions); - const expected = { - additionalProperties: { prop: 43.125 }, + const expected: IsFloatAdditionalProperties = { id: 43.125, + prop: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -116,9 +125,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("SpreadFloat", () => { const client = new SpreadFloatClient(clientOptions); - const expected = { - additionalProperties: { prop: 43.125 }, + const expected: SpreadFloatRecord = { id: 43.125, + prop: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -131,9 +140,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("ExtendsModel", () => { const client = new ExtendsModelClient(clientOptions); - const expected = { + const expected: ExtendsModelAdditionalProperties = { knownProp: { state: "ok" }, - additionalProperties: { prop: { state: "ok" } }, + prop: { state: "ok" }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -146,9 +155,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("IsModel", () => { const client = new IsModelClient(clientOptions); - const expected = { + const expected: IsModelAdditionalProperties = { knownProp: { state: "ok" }, - additionalProperties: { prop: { state: "ok" } }, + prop: { state: "ok" }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -161,9 +170,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("SpreadModel", () => { const client = new SpreadModelClient(clientOptions); - const expected = { + const expected: SpreadModelRecord = { knownProp: { state: "ok" }, - additionalProperties: { prop: { state: "ok" } }, + prop: { state: "ok" }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -176,9 +185,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("ExtendsModelArray", () => { const client = new ExtendsModelArrayClient(clientOptions); - const expected = { + const expected: ExtendsModelArrayAdditionalProperties = { knownProp: [{ state: "ok" }, { state: "ok" }], - additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, + prop: [{ state: "ok" }, { state: "ok" }], }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -191,9 +200,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("IsModelArray", () => { const client = new IsModelArrayClient(clientOptions); - const expected = { + const expected: IsModelArrayAdditionalProperties = { knownProp: [{ state: "ok" }, { state: "ok" }], - additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, + prop: [{ state: "ok" }, { state: "ok" }], }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -206,9 +215,9 @@ describe("Missing AdditionalProperties Endpoints", () => { describe("SpreadModelArray", () => { const client = new SpreadModelArrayClient(clientOptions); - const expected = { + const expected: SpreadModelArrayRecord = { knownProp: [{ state: "ok" }, { state: "ok" }], - additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, + prop: [{ state: "ok" }, { state: "ok" }], }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -224,14 +233,14 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentStringClient(clientOptions); const expected = { id: 43.125, - additionalProperties: { prop: "abc" }, + prop: "abc", }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -239,14 +248,14 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentFloatClient(clientOptions); const expected = { name: "abc", - additionalProperties: { prop: 43.125 }, + prop: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -254,14 +263,14 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentModelClient(clientOptions); const expected = { knownProp: "abc", - additionalProperties: { prop: { state: "ok" } }, + prop: { state: "ok" }, }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -269,14 +278,14 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentModelArrayClient(clientOptions); const expected = { knownProp: "abc", - additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, + prop: [{ state: "ok" }, { state: "ok" }], }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -284,7 +293,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadStringClient(clientOptions); const expected = { id: 43.125, - additionalProperties: { prop: "abc" }, + prop: "abc", derivedProp: "abc", }; it("GET returns the expected response", async () => { @@ -292,7 +301,7 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -300,7 +309,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadFloatClient(clientOptions); const expected = { name: "abc", - additionalProperties: { prop: 43.125 }, + prop: 43.125, derivedProp: 43.125, }; it("GET returns the expected response", async () => { @@ -308,7 +317,7 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -316,7 +325,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadModelClient(clientOptions); const expected = { knownProp: "abc", - additionalProperties: { prop: { state: "ok" } }, + prop: { state: "ok" }, derivedProp: { state: "ok" }, }; it("GET returns the expected response", async () => { @@ -324,7 +333,7 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -332,7 +341,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadModelArrayClient(clientOptions); const expected = { knownProp: "abc", - additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, + prop: [{ state: "ok" }, { state: "ok" }], derivedProp: [{ state: "ok" }, { state: "ok" }], }; it("GET returns the expected response", async () => { @@ -340,7 +349,7 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -349,14 +358,15 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new MultipleSpreadClient(clientOptions); const expected = { flag: true, - additionalProperties: { prop1: "abc", prop2: 43.125 }, + prop1: "abc", + prop2: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); @@ -364,28 +374,27 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadRecordUnionClient(clientOptions); const expected = { flag: true, - additionalProperties: { prop1: "abc", prop2: 43.125 }, + prop1: "abc", + prop2: 43.125, }; it("GET returns the expected response", async () => { const response = await client.get(); expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); describe("SpreadRecordNonDiscriminatedUnion", () => { const client = new SpreadRecordNonDiscriminatedUnionClient(clientOptions); - const expected: SpreadRecordForNonDiscriminatedUnion = { + const expected = { name: "abc", - additionalProperties: { - prop1: { kind: "kind0", fooProp: "abc" }, - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", - } as any, + prop1: { kind: "kind0", fooProp: "abc" }, + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", }, }; it("GET returns the expected response", async () => { @@ -393,21 +402,19 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); describe("SpreadRecordNonDiscriminatedUnion2", () => { const client = new SpreadRecordNonDiscriminatedUnion2Client(clientOptions); - const expected: SpreadRecordForNonDiscriminatedUnion2 = { + const expected = { name: "abc", - additionalProperties: { - prop1: { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", - } as any, + prop1: { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", }, }; it("GET returns the expected response", async () => { @@ -415,24 +422,22 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); describe("SpreadRecordNonDiscriminatedUnion3", () => { const client = new SpreadRecordNonDiscriminatedUnion3Client(clientOptions); - const expected: SpreadRecordForNonDiscriminatedUnion3 = { + const expected = { name: "abc", - additionalProperties: { - prop1: [ - { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - ], - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", - } as any, + prop1: [ + { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + ], + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", }, }; it("GET returns the expected response", async () => { @@ -440,7 +445,7 @@ describe("Missing AdditionalProperties Endpoints", () => { expect(response).toEqual(expected); }); it("PUT accepts the expected input", async () => { - await client.put(expected); + await client.put(expected as any); }); }); }); diff --git a/packages/http-client-js/test/scenarios/additional-properties/extends.md b/packages/http-client-js/test/scenarios/additional-properties/extends.md index f9b45861f64..71890fcb603 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/extends.md +++ b/packages/http-client-js/test/scenarios/additional-properties/extends.md @@ -37,7 +37,7 @@ export function jsonWidgetToTransportTransform(input_?: Widget | null): any { return input_ as any; } return { - ...jsonRecordUnknownToTransportTransform(input_.additionalProperties), + ...jsonRecordUnknownToTransportTransform((({ name, age, optional, ...rest }) => rest)(input_)), name: input_.name, age: input_.age, optional: input_.optional, @@ -55,7 +55,7 @@ export function jsonWidgetToApplicationTransform(input_?: any): Widget { return input_ as any; } return { - additionalProperties: jsonRecordUnknownToApplicationTransform( + ...jsonRecordUnknownToApplicationTransform( (({ name, age, optional, ...rest }) => rest)(input_), ), name: input_.name, diff --git a/packages/http-client-js/test/scenarios/additional-properties/spread.md b/packages/http-client-js/test/scenarios/additional-properties/spread.md index 387bb80f68c..218d800715f 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/spread.md +++ b/packages/http-client-js/test/scenarios/additional-properties/spread.md @@ -21,7 +21,7 @@ op foo(): Widget; Should generate a model with name `Widget` with the known properties in the root and an evelop property called `additionalProperties` ```ts src/models/models.ts interface Widget -export interface Widget extends Record { +export interface Widget { name: string; age: number; optional?: string; @@ -38,7 +38,7 @@ export function jsonWidgetToTransportTransform(input_?: Widget | null): any { return input_ as any; } return { - ...jsonRecordStringToTransportTransform(input_.additionalProperties), + ...jsonRecordStringToTransportTransform((({ name, age, optional, ...rest }) => rest)(input_)), name: input_.name, age: input_.age, optional: input_.optional, @@ -56,9 +56,7 @@ export function jsonWidgetToApplicationTransform(input_?: any): Widget { return input_ as any; } return { - additionalProperties: jsonRecordStringToApplicationTransform( - (({ name, age, optional, ...rest }) => rest)(input_), - ), + ...jsonRecordStringToApplicationTransform((({ name, age, optional, ...rest }) => rest)(input_)), name: input_.name, age: input_.age, optional: input_.optional, diff --git a/packages/http-client-js/test/scenarios/models/model_additional_properties.md b/packages/http-client-js/test/scenarios/models/model_additional_properties.md index cd2c28b4d04..7506db54c57 100644 --- a/packages/http-client-js/test/scenarios/models/model_additional_properties.md +++ b/packages/http-client-js/test/scenarios/models/model_additional_properties.md @@ -32,7 +32,7 @@ export interface ExtraFeature { ``` ```ts src/models/models.ts interface Dog -export interface Dog extends Record { +export interface Dog { id: string; name: string; color: "black" | "brown"; @@ -47,7 +47,7 @@ export function jsonDogToTransportTransform(input_?: Dog | null): any { return input_ as any; } return { - ...jsonRecordExtraFeatureToTransportTransform(input_.additionalProperties), + ...jsonRecordExtraFeatureToTransportTransform((({ id, name, color, ...rest }) => rest)(input_)), id: input_.id, name: input_.name, color: input_.color, @@ -63,7 +63,7 @@ export function jsonDogToApplicationTransform(input_?: any): Dog { return input_ as any; } return { - additionalProperties: jsonRecordExtraFeatureToApplicationTransform( + ...jsonRecordExtraFeatureToApplicationTransform( (({ id, name, color, ...rest }) => rest)(input_), ), id: input_.id, diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md index d3207af88a1..7d949a35e71 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md @@ -47,7 +47,7 @@ export function jsonSpreadRecordForDiscriminatedUnionToTransportTransform( return input_ as any; } return { - ...jsonRecordWidgetDataToTransportTransform(input_.additionalProperties), + ...jsonRecordWidgetDataToTransportTransform((({ name, ...rest }) => rest)(input_)), name: input_.name, }!; } @@ -61,9 +61,7 @@ export function jsonSpreadRecordForDiscriminatedUnionToApplicationTransform( return input_ as any; } return { - additionalProperties: jsonRecordWidgetDataToApplicationTransform( - (({ name, ...rest }) => rest)(input_), - ), + ...jsonRecordWidgetDataToApplicationTransform((({ name, ...rest }) => rest)(input_)), name: input_.name, }!; } From 789af83429d8e4e7007598ad40fe6546afb2df61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:16:19 +0000 Subject: [PATCH 6/7] test(emitter-framework): add test case for incompatible property types skipping extends Record Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../components/interface-declaration.test.tsx | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx index a012a4d84c3..3448146abb1 100644 --- a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx +++ b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx @@ -332,6 +332,32 @@ describe("Typescript Interface", () => { }`); }); + it("omits extends clause when known properties are incompatible with the record element type", async () => { + const program = await getProgram(` + namespace DemoService; + model Widget { + id: int32; + ...Record; + } + `); + + const [namespace] = program.resolveTypeReference("DemoService"); + const models = Array.from((namespace as Namespace).models.values()); + + expect( + + + {models.map((model) => ( + + ))} + + , + ).toRenderTo(` + export interface Widget { + id: number; + }`); + }); + it("handles a type reference to a union variant", async () => { const program = await getProgram(` namespace DemoService; From c0acb371d70de8ccbc1e87eb96ed184b1de3a66f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 23:03:23 +0000 Subject: [PATCH 7/7] fix(emitter-framework): add additionalProperties for incompatible record types, use extends Record for compatible types - InterfaceBody now adds additionalProperties?: Record when named properties are incompatible with the record element type (TypeScript index signature constraint) - getExtendsType already skips extends clause for incompatible cases - json-model-additional-properties-transform uses wrapper approach (input_.additionalProperties) for incompatible types and flat approach (destructuring) for compatible types - Added multiple record spreads test (model Foo { id: int32; ...Record; ...Record }) showing union additionalProperties - Updated test snapshots to reflect new behavior - Updated e2e tests to use additionalProperties wrapper for DifferentSpread/MultipleSpread types Co-authored-by: markcowl <1054056+markcowl@users.noreply.github.com> --- .../components/interface-declaration.tsx | 23 +++++++ .../components/interface-declaration.test.tsx | 32 +++++++++- ...-model-additional-properties-transform.tsx | 59 ++++++++++++++++- .../additional-properties/spreads.test.ts | 64 ++++++++++--------- .../scenarios/additional-properties/spread.md | 7 +- .../models/model_additional_properties.md | 5 +- .../serializers/discriminated_union_spread.md | 6 +- 7 files changed, 157 insertions(+), 39 deletions(-) diff --git a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx index 2dc97fd9517..f5d936c1944 100644 --- a/packages/emitter-framework/src/typescript/components/interface-declaration.tsx +++ b/packages/emitter-framework/src/typescript/components/interface-declaration.tsx @@ -132,9 +132,32 @@ function getExtendsType($: Typekit, type: Model | Interface): Children | undefin */ function InterfaceBody(props: TypedInterfaceDeclarationProps): Children { const { $ } = useTsp(); + const additionalPropertiesKey = "additionalProperties"; let typeMembers: RekeyableMap | undefined; if ($.model.is(props.type)) { typeMembers = $.model.getProperties(props.type); + + // When the model has a record indexer (from ...Record spreads) but the named + // properties are not assignable to the element type, TypeScript cannot represent + // this with `extends Record` (index signature compatibility constraint). + // Instead, add an `additionalProperties` named property to represent the extra properties. + const indexType = $.model.getIndexType(props.type); + if (indexType && $.record.is(indexType)) { + const elementType = indexType.indexer!.value; + const allCompatible = Array.from(typeMembers.values()).every((prop) => + $.modelProperty.is(prop) ? $.type.isAssignableTo(prop.type, elementType) : true, + ); + if (!allCompatible) { + typeMembers.set( + additionalPropertiesKey, + $.modelProperty.create({ + name: additionalPropertiesKey, + optional: true, + type: indexType, + }), + ); + } + } } else { typeMembers = createRekeyableMap(props.type.operations); } diff --git a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx index 3448146abb1..15d8c6e43c0 100644 --- a/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx +++ b/packages/emitter-framework/test/typescript/components/interface-declaration.test.tsx @@ -297,6 +297,7 @@ describe("Typescript Interface", () => { } export interface DifferentSpreadModelRecord { knownProp: string; + additionalProperties?: Record; } export interface DifferentSpreadModelDerived extends DifferentSpreadModelRecord { derivedProp: ModelForRecord; @@ -332,7 +333,7 @@ describe("Typescript Interface", () => { }`); }); - it("omits extends clause when known properties are incompatible with the record element type", async () => { + it("adds additionalProperties when known properties are incompatible with the record element type", async () => { const program = await getProgram(` namespace DemoService; model Widget { @@ -355,6 +356,35 @@ describe("Typescript Interface", () => { ).toRenderTo(` export interface Widget { id: number; + additionalProperties?: Record; + }`); + }); + + it("adds additionalProperties for multiple incompatible record spreads as a union type", async () => { + const program = await getProgram(` + namespace DemoService; + model Foo { + id: int32; + ...Record; + ...Record; + } + `); + + const [namespace] = program.resolveTypeReference("DemoService"); + const models = Array.from((namespace as Namespace).models.values()); + + expect( + + + {models.map((model) => ( + + ))} + + , + ).toRenderTo(` + export interface Foo { + id: number; + additionalProperties?: Record; }`); }); diff --git a/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx b/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx index 1ac38e645e1..31544aecd65 100644 --- a/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx +++ b/packages/http-client-js/src/components/transforms/json/json-model-additional-properties-transform.tsx @@ -1,4 +1,5 @@ import { Children, code, mapJoin } from "@alloy-js/core"; +import * as ts from "@alloy-js/typescript"; import type { Model } from "@typespec/compiler"; import { useTsp } from "@typespec/emitter-framework"; import { getJsonRecordTransformRefkey } from "./json-record-transform.jsx"; @@ -9,6 +10,36 @@ export interface JsonAdditionalPropertiesTransformProps { target: "transport" | "application"; } +/** + * Determines whether a model uses the `additionalProperties` wrapper property + * (instead of flat spreading). This is true when the model has a record index type + * from spreads but the named properties are not all assignable to the element type, + * or when an ancestor model uses the wrapper approach. + */ +function usesWrappedAdditionalProperties($: ReturnType["$"], type: Model): boolean { + const indexType = $.model.getIndexType(type); + if (indexType && $.record.is(indexType)) { + const elementType = indexType.indexer!.value; + const properties = $.model.getProperties(type); + const allCompatible = Array.from(properties.values()).every((prop) => + $.modelProperty.is(prop) ? $.type.isAssignableTo(prop.type, elementType) : true, + ); + return !allCompatible; + } + + // Direct base is a record (extends Record) → always flat + if (type.baseModel && $.record.is(type.baseModel)) { + return false; + } + + // Recurse into base model to check if the wrapper comes from inheritance + if (type.baseModel) { + return usesWrappedAdditionalProperties($, type.baseModel); + } + + return false; +} + export function JsonAdditionalPropertiesTransform(props: JsonAdditionalPropertiesTransformProps) { const { $ } = useTsp(); const additionalProperties = $.model.getAdditionalPropertiesRecord(props.type); @@ -27,10 +58,34 @@ export function JsonAdditionalPropertiesTransform(props: JsonAdditionalPropertie }, ); - // Extract additional properties by destructuring known properties and spreading the rest + if (usesWrappedAdditionalProperties($, props.type)) { + // Incompatible case: use additionalProperties wrapper property + if (props.target === "application") { + const inlineDestructure = code` + ${getJsonRecordTransformRefkey(additionalProperties, props.target)}( + (({ ${destructuredProperties} ...rest }) => rest)(${props.itemRef}) + ), + `; + + return ( + <> + {inlineDestructure} + + ); + } + + const itemRef = code`${props.itemRef}.additionalProperties`; + + return ( + <> + ...({getJsonRecordTransformRefkey(additionalProperties, props.target)}({itemRef}) ), + + ); + } + + // Compatible case: spread additional properties directly onto the object const restExpr = code`(({ ${destructuredProperties} ...rest }) => rest)(${props.itemRef})`; - // Spread additional properties directly onto the object (not wrapped in additionalProperties) return ( <> ...({getJsonRecordTransformRefkey(additionalProperties, props.target)}({restExpr}) ), diff --git a/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts b/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts index 783b7314c59..a9ba339f4e2 100644 --- a/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts +++ b/packages/http-client-js/test/e2e/http/type/property/additional-properties/spreads.test.ts @@ -233,7 +233,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentStringClient(clientOptions); const expected = { id: 43.125, - prop: "abc", + additionalProperties: { prop: "abc" }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -248,7 +248,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentFloatClient(clientOptions); const expected = { name: "abc", - prop: 43.125, + additionalProperties: { prop: 43.125 }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -263,7 +263,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentModelClient(clientOptions); const expected = { knownProp: "abc", - prop: { state: "ok" }, + additionalProperties: { prop: { state: "ok" } }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -278,7 +278,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadDifferentModelArrayClient(clientOptions); const expected = { knownProp: "abc", - prop: [{ state: "ok" }, { state: "ok" }], + additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -293,8 +293,8 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadStringClient(clientOptions); const expected = { id: 43.125, - prop: "abc", derivedProp: "abc", + additionalProperties: { prop: "abc" }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -309,8 +309,8 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadFloatClient(clientOptions); const expected = { name: "abc", - prop: 43.125, derivedProp: 43.125, + additionalProperties: { prop: 43.125 }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -325,8 +325,8 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadModelClient(clientOptions); const expected = { knownProp: "abc", - prop: { state: "ok" }, derivedProp: { state: "ok" }, + additionalProperties: { prop: { state: "ok" } }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -341,8 +341,8 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new ExtendsDifferentSpreadModelArrayClient(clientOptions); const expected = { knownProp: "abc", - prop: [{ state: "ok" }, { state: "ok" }], derivedProp: [{ state: "ok" }, { state: "ok" }], + additionalProperties: { prop: [{ state: "ok" }, { state: "ok" }] }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -358,8 +358,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new MultipleSpreadClient(clientOptions); const expected = { flag: true, - prop1: "abc", - prop2: 43.125, + additionalProperties: { prop1: "abc", prop2: 43.125 }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -374,8 +373,7 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadRecordUnionClient(clientOptions); const expected = { flag: true, - prop1: "abc", - prop2: 43.125, + additionalProperties: { prop1: "abc", prop2: 43.125 }, }; it("GET returns the expected response", async () => { const response = await client.get(); @@ -390,11 +388,13 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadRecordNonDiscriminatedUnionClient(clientOptions); const expected = { name: "abc", - prop1: { kind: "kind0", fooProp: "abc" }, - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", + additionalProperties: { + prop1: { kind: "kind0", fooProp: "abc" }, + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", + }, }, }; it("GET returns the expected response", async () => { @@ -410,11 +410,13 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadRecordNonDiscriminatedUnion2Client(clientOptions); const expected = { name: "abc", - prop1: { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", + additionalProperties: { + prop1: { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", + }, }, }; it("GET returns the expected response", async () => { @@ -430,14 +432,16 @@ describe("Missing AdditionalProperties Endpoints", () => { const client = new SpreadRecordNonDiscriminatedUnion3Client(clientOptions); const expected = { name: "abc", - prop1: [ - { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - { kind: "kind1", start: "2021-01-01T00:00:00Z" }, - ], - prop2: { - kind: "kind1", - start: "2021-01-01T00:00:00Z", - end: "2021-01-02T00:00:00Z", + additionalProperties: { + prop1: [ + { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + { kind: "kind1", start: "2021-01-01T00:00:00Z" }, + ], + prop2: { + kind: "kind1", + start: "2021-01-01T00:00:00Z", + end: "2021-01-02T00:00:00Z", + }, }, }; it("GET returns the expected response", async () => { diff --git a/packages/http-client-js/test/scenarios/additional-properties/spread.md b/packages/http-client-js/test/scenarios/additional-properties/spread.md index 218d800715f..963e5108cc4 100644 --- a/packages/http-client-js/test/scenarios/additional-properties/spread.md +++ b/packages/http-client-js/test/scenarios/additional-properties/spread.md @@ -25,6 +25,7 @@ export interface Widget { name: string; age: number; optional?: string; + additionalProperties?: Record; } ``` @@ -38,7 +39,7 @@ export function jsonWidgetToTransportTransform(input_?: Widget | null): any { return input_ as any; } return { - ...jsonRecordStringToTransportTransform((({ name, age, optional, ...rest }) => rest)(input_)), + ...jsonRecordStringToTransportTransform(input_.additionalProperties), name: input_.name, age: input_.age, optional: input_.optional, @@ -56,7 +57,9 @@ export function jsonWidgetToApplicationTransform(input_?: any): Widget { return input_ as any; } return { - ...jsonRecordStringToApplicationTransform((({ name, age, optional, ...rest }) => rest)(input_)), + additionalProperties: jsonRecordStringToApplicationTransform( + (({ name, age, optional, ...rest }) => rest)(input_), + ), name: input_.name, age: input_.age, optional: input_.optional, diff --git a/packages/http-client-js/test/scenarios/models/model_additional_properties.md b/packages/http-client-js/test/scenarios/models/model_additional_properties.md index 7506db54c57..924b99e456c 100644 --- a/packages/http-client-js/test/scenarios/models/model_additional_properties.md +++ b/packages/http-client-js/test/scenarios/models/model_additional_properties.md @@ -36,6 +36,7 @@ export interface Dog { id: string; name: string; color: "black" | "brown"; + additionalProperties?: Record; } ``` @@ -47,7 +48,7 @@ export function jsonDogToTransportTransform(input_?: Dog | null): any { return input_ as any; } return { - ...jsonRecordExtraFeatureToTransportTransform((({ id, name, color, ...rest }) => rest)(input_)), + ...jsonRecordExtraFeatureToTransportTransform(input_.additionalProperties), id: input_.id, name: input_.name, color: input_.color, @@ -63,7 +64,7 @@ export function jsonDogToApplicationTransform(input_?: any): Dog { return input_ as any; } return { - ...jsonRecordExtraFeatureToApplicationTransform( + additionalProperties: jsonRecordExtraFeatureToApplicationTransform( (({ id, name, color, ...rest }) => rest)(input_), ), id: input_.id, diff --git a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md index 7d949a35e71..d3207af88a1 100644 --- a/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md +++ b/packages/http-client-js/test/scenarios/serializers/discriminated_union_spread.md @@ -47,7 +47,7 @@ export function jsonSpreadRecordForDiscriminatedUnionToTransportTransform( return input_ as any; } return { - ...jsonRecordWidgetDataToTransportTransform((({ name, ...rest }) => rest)(input_)), + ...jsonRecordWidgetDataToTransportTransform(input_.additionalProperties), name: input_.name, }!; } @@ -61,7 +61,9 @@ export function jsonSpreadRecordForDiscriminatedUnionToApplicationTransform( return input_ as any; } return { - ...jsonRecordWidgetDataToApplicationTransform((({ name, ...rest }) => rest)(input_)), + additionalProperties: jsonRecordWidgetDataToApplicationTransform( + (({ name, ...rest }) => rest)(input_), + ), name: input_.name, }!; }