Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/typespec-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"@typespec/spector": "0.1.0-alpha.24-dev.2",
"@typespec/spec-api": "0.1.0-dev.0",
"@typespec/tspd": "0.74.0",
"@azure-tools/azure-http-specs": "0.1.0-alpha.38-dev.2",
"@azure-tools/azure-http-specs": "0.1.0-alpha.38-dev.6",
"@azure-tools/typespec-autorest": "^0.65.0",
"@azure-tools/typespec-azure-core": "^0.65.0",
"@azure-tools/typespec-azure-resource-manager": "^0.65.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,16 @@ function buildModelTypeSerializer(
output.push(`
return ${serializeContent}
`);
} else if (options.flatten) {
// Private flatten serializer: all child properties are read-only, so nothing to serialize.
// Rename the parameter to _item to avoid TypeScript unused-variable errors.
const firstParam = serializerFunction.parameters?.[0];
if (firstParam) {
firstParam.name = "_item";
}
output.push(`
return {};
`);
} else {
output.push(`
return item;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ export declare type FlattenPropertyClient = Client & {
export declare interface FlattenPropertyClientOptions extends ClientOptions {
}

export declare interface FlattenUnknownModel {
name: string;
properties?: unknown;
}

export declare interface FlattenUnknownModelOutput {
name: string;
properties?: any;
}

export declare interface NestedFlattenModel {
name: string;
properties: ChildFlattenModel;
Expand All @@ -69,6 +79,36 @@ export declare interface PutFlattenModelBodyParam {

export declare type PutFlattenModelParameters = PutFlattenModelBodyParam & RequestParameters;

export declare interface PutFlattenReadOnlyModel {
put(options: PutFlattenReadOnlyModelParameters): StreamableMethod<PutFlattenReadOnlyModel200Response>;
}

export declare interface PutFlattenReadOnlyModel200Response extends HttpResponse {
status: "200";
body: SolutionOutput;
}

export declare interface PutFlattenReadOnlyModelBodyParam {
body: Solution;
}

export declare type PutFlattenReadOnlyModelParameters = PutFlattenReadOnlyModelBodyParam & RequestParameters;

export declare interface PutFlattenUnknownModel {
put(options: PutFlattenUnknownModelParameters): StreamableMethod<PutFlattenUnknownModel200Response>;
}

export declare interface PutFlattenUnknownModel200Response extends HttpResponse {
status: "200";
body: FlattenUnknownModelOutput;
}

export declare interface PutFlattenUnknownModelBodyParam {
body: FlattenUnknownModel;
}

export declare type PutFlattenUnknownModelParameters = PutFlattenUnknownModelBodyParam & RequestParameters;

export declare interface PutNestedFlattenModel {
put(options: PutNestedFlattenModelParameters): StreamableMethod<PutNestedFlattenModel200Response>;
}
Expand All @@ -87,6 +127,27 @@ export declare type PutNestedFlattenModelParameters = PutNestedFlattenModelBodyP
export declare interface Routes {
(path: "/azure/client-generator-core/flatten-property/flattenModel"): PutFlattenModel;
(path: "/azure/client-generator-core/flatten-property/nestedFlattenModel"): PutNestedFlattenModel;
(path: "/azure/client-generator-core/flatten-property/flattenUnknownModel"): PutFlattenUnknownModel;
(path: "/azure/client-generator-core/flatten-property/flattenReadOnlyModel"): PutFlattenReadOnlyModel;
}

export declare interface Solution {
name: string;
properties?: SolutionProperties;
}

export declare interface SolutionOutput {
name: string;
properties?: SolutionPropertiesOutput;
}

export declare interface SolutionProperties {
}

export declare interface SolutionPropertiesOutput {
readonly solutionId?: string;
readonly title?: string;
readonly content?: string;
}

export { }
33 changes: 33 additions & 0 deletions packages/typespec-ts/test/azureIntegration/modelFlatten.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,37 @@ describe("Flatten Property Rest Client", () => {
assert.strictEqual(result.body.properties.properties.description, "foo");
assert.strictEqual(result.body.properties.properties.age, 1);
});

it("should update and receive model with unknown flatten property", async () => {
const result = await client
.path("/azure/client-generator-core/flatten-property/flattenUnknownModel")
.put({
body: {
name: "foo"
}
});
assert.strictEqual(result.status, "200");
assert.strictEqual(result.body.name, "test");
assert.deepEqual(result.body.properties, {
key1: "value1",
key2: "value2"
});
});

it("should update and receive model with all readonly flatten properties", async () => {
const result = await client
.path(
"/azure/client-generator-core/flatten-property/flattenReadOnlyModel"
)
.put({
body: {
name: "foo"
}
});
assert.strictEqual(result.status, "200");
assert.strictEqual(result.body.name, "foo");
assert.strictEqual(result.body.properties?.solutionId, "solution1");
assert.strictEqual(result.body.properties?.title, "Solution Title");
assert.strictEqual(result.body.properties?.content, "Solution Content");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ export declare class FlattenPropertyClient {
private _client;
readonly pipeline: Pipeline;
constructor(options?: FlattenPropertyClientOptionalParams);
putFlattenReadOnlyModel(body: Solution, options?: PutFlattenReadOnlyModelOptionalParams): Promise<Solution>;
putFlattenUnknownModel(input: FlattenUnknownModel, options?: PutFlattenUnknownModelOptionalParams): Promise<FlattenUnknownModel>;
putNestedFlattenModel(input: NestedFlattenModel, options?: PutNestedFlattenModelOptionalParams): Promise<NestedFlattenModel>;
putFlattenModel(input: FlattenModel, options?: PutFlattenModelOptionalParams): Promise<FlattenModel>;
}

export declare interface FlattenPropertyClientOptionalParams extends ClientOptions {
}

export declare interface FlattenUnknownModel {
name: string;
properties?: any;
}

export declare interface NestedFlattenModel {
name: string;
summary: string;
Expand All @@ -39,7 +46,26 @@ export declare interface NestedFlattenModel {
export declare interface PutFlattenModelOptionalParams extends OperationOptions {
}

export declare interface PutFlattenReadOnlyModelOptionalParams extends OperationOptions {
}

export declare interface PutFlattenUnknownModelOptionalParams extends OperationOptions {
}

export declare interface PutNestedFlattenModelOptionalParams extends OperationOptions {
}

export declare interface Solution {
name: string;
readonly solutionId?: string;
readonly title?: string;
readonly content?: string;
}

export declare interface SolutionProperties {
readonly solutionId?: string;
readonly title?: string;
readonly content?: string;
}

export { }
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,23 @@ describe("Property Flatten Client", () => {
assert.strictEqual(result.properties.description, "foo");
assert.strictEqual(result.properties.age, 1);
});

it("Update and receive model with unknown properties flattening", async () => {
const result = await client.putFlattenUnknownModel({
name: "foo"
});
assert.strictEqual(result.name, "test");
assert.strictEqual(result.properties?.key1, "value1");
assert.strictEqual(result.properties?.key2, "value2");
});

it("Update and receive model with read-only properties flattening", async () => {
const result = await client.putFlattenReadOnlyModel({
name: "foo"
});
assert.strictEqual(result.name, "foo");
assert.strictEqual(result.solutionId, "solution1");
assert.strictEqual(result.title, "Solution Title");
assert.strictEqual(result.content, "Solution Content");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,94 @@ export function solutionPropertiesSerializer(item: SolutionProperties): any {
return item;
}

export function _solutionPropertiesSerializer(_item: Solution): any {
return {};
}

export function _solutionPropertiesOptionalSerializer(_item: Solution): any {
return {};
}
```

# Should handle flatten model with not all readonly properties correctly

## TypeSpec

This is tsp definition.

```tsp

model SolutionProperties {
solutionId?: string;
title?: string;
@visibility(Lifecycle.Read)
content?: string;
}
model Solution{
@Azure.ClientGenerator.Core.Legacy.flattenProperty
properties: SolutionProperties;
@Azure.ClientGenerator.Core.Legacy.flattenProperty
propertiesOptional?: SolutionProperties;
}
op test(@body body:Solution):void;

```

Enable the raw content with TCGC dependency.

```yaml
needTCGC: true
```

## Models

```ts models
import { areAllPropsUndefined } from "../static-helpers/serialization/check-prop-undefined.js";

/**
* This file contains only generated model types and their (de)serializers.
* Disable the following rules for internal models with '_' prefix and deserializers which require 'any' for raw JSON input.
*/
/* eslint-disable @typescript-eslint/naming-convention */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/** model interface Solution */
export interface Solution {
solutionId?: string;
title?: string;
readonly content?: string;
solutionIdPropertiesOptionalSolutionId?: string;
titlePropertiesOptionalTitle?: string;
readonly contentPropertiesOptionalContent?: string;
}

export function solutionSerializer(item: Solution): any {
return {
properties: _solutionPropertiesSerializer(item),
propertiesOptional: areAllPropsUndefined(item, ["solutionId", "title"])
? undefined
: _solutionPropertiesOptionalSerializer(item),
};
}

/** model interface SolutionProperties */
export interface SolutionProperties {
solutionId?: string;
title?: string;
readonly content?: string;
}

export function solutionPropertiesSerializer(item: SolutionProperties): any {
return { solutionId: item["solutionId"], title: item["title"] };
}

export function _solutionPropertiesSerializer(item: Solution): any {
return item;
return { solutionId: item["solutionId"], title: item["title"] };
}

export function _solutionPropertiesOptionalSerializer(item: Solution): any {
return item;
return {
solutionId: item["solutionIdPropertiesOptionalSolutionId"],
title: item["titlePropertiesOptionalTitle"],
};
}
```
12 changes: 6 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading