Skip to content

Commit 9927227

Browse files
Merge branch 'main' into type-import-base-flag
2 parents 62ab39d + 6ebff38 commit 9927227

382 files changed

Lines changed: 12628 additions & 4316 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
3+
changeKind: fix
4+
packages:
5+
- "@typespec/graphql"
6+
---
7+
8+
Add `./mutation-engine` subpath export for standalone mutation pipeline usage
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: internal
3+
packages:
4+
- "@typespec/http-client-java"
5+
---
6+
7+
Bump dependencies
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: internal
3+
packages:
4+
- "@typespec/http-client-java"
5+
---
6+
7+
Make the diagnostic documentation source path configurable for reuse across emitter packages.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: internal
3+
packages:
4+
- "@typespec/http-client-java"
5+
---
6+
7+
Add reference documentation for Java emitter diagnostics.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
changeKind: feature
3+
packages:
4+
- "@typespec/http-client-python"
5+
---
6+
7+
Add a `generate-typeddict` emitter option (default `true`) that controls `TypedDict` generation independently of `models-mode`. `models-mode` now toggles just `dpg` and `none`; the `typeddict` value is deprecated.

.github/workflows/copilot-setup-steps.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ jobs:
2121
- name: Checkout repository
2222
uses: actions/checkout@v7
2323
- name: Install gh-aw extension
24-
uses: github/gh-aw/actions/setup-cli@v0.82.14
24+
uses: github/gh-aw/actions/setup-cli@v0.83.4
2525
with:
2626
version: v0.50.1

packages/graphql/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
"typespec": "./lib/main.tsp",
2525
"types": "./dist/src/index.d.ts",
2626
"default": "./dist/src/index.js"
27+
},
28+
"./mutation-engine": {
29+
"types": "./dist/src/mutation-engine/index.d.ts",
30+
"default": "./dist/src/mutation-engine/index.js"
2731
}
2832
},
2933
"engines": {

packages/graphql/src/mutation-engine/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export { resolveTypeUsage, type TypeUsageResolver } from "../type-usage.js";
12
export { GraphQLMutationEngine, createGraphQLMutationEngine } from "./engine.js";
23
export {
34
GraphQLEnumMemberMutation,

packages/http-client-csharp/emitter/src/lib/operation-converter.ts

Lines changed: 112 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
SdkQueryParameter,
2020
SdkServiceMethod,
2121
SdkServiceResponseHeader,
22+
SdkStreamMetadata,
2223
SdkType,
2324
} from "@azure-tools/typespec-client-generator-core";
2425
import {
@@ -30,15 +31,18 @@ import {
3031
shouldGenerateConvenient,
3132
shouldGenerateProtocol,
3233
} from "@azure-tools/typespec-client-generator-core";
33-
import type { Diagnostic } from "@typespec/compiler";
34+
import type { Diagnostic, Union } from "@typespec/compiler";
3435
import {
36+
compilerAssert,
3537
createDiagnosticCollector,
3638
getDeprecated,
3739
isErrorModel,
3840
NoTarget,
3941
} from "@typespec/compiler";
42+
import { unsafe_getEventDefinitions } from "@typespec/events/experimental";
4043
import type { HttpStatusCodeRange } from "@typespec/http";
4144
import { getResourceOperation } from "@typespec/rest";
45+
import { isTerminalEvent } from "@typespec/sse";
4246
import type { CSharpEmitterContext } from "../sdk-context.js";
4347
import { collectionFormatToDelimMap } from "../type/collection-format.js";
4448
import type { HttpResponseHeader } from "../type/http-response-header.js";
@@ -64,6 +68,7 @@ import type {
6468
InputMethodParameter,
6569
InputPathParameter,
6670
InputQueryParameter,
71+
InputStreamingType,
6772
InputType,
6873
} from "../type/input-type.js";
6974
import { convertLroFinalStateVia } from "../type/operation-final-state-via.js";
@@ -234,7 +239,9 @@ export function fromSdkServiceMethodOperation(
234239
path: method.operation.path,
235240
externalDocsUrl: getExternalDocs(sdkContext, method.operation.__raw.operation)?.url,
236241
requestMediaTypes: requestMediaTypes,
237-
bufferResponse: true,
242+
bufferResponse: !method.operation.responses.some((response) =>
243+
isSupportedStream(response.streamMetadata),
244+
),
238245
generateProtocolMethod: shouldGenerateProtocol(sdkContext, method.operation.__raw.operation),
239246
generateConvenienceMethod: generateConvenience,
240247
crossLanguageDefinitionId: method.crossLanguageDefinitionId,
@@ -351,8 +358,23 @@ function fromSdkServiceMethodParameters(
351358
for (const p of method.parameters) {
352359
const methodInputParameter = diagnostics.pipe(fromMethodParameter(sdkContext, p, namespace));
353360
const operationHttpParameter = getHttpOperationParameter(method, p);
361+
const streamMetadata = method.operation.bodyParam?.streamMetadata;
362+
const isStreamingBodyParameter =
363+
isJsonLinesStream(streamMetadata) &&
364+
method.operation.bodyParam!.methodParameterSegments.some((segments) =>
365+
segments.some(
366+
(segment) =>
367+
segment === p || segment.crossLanguageDefinitionId === p.crossLanguageDefinitionId,
368+
),
369+
);
354370

355371
if (!operationHttpParameter) {
372+
if (isStreamingBodyParameter) {
373+
methodInputParameter.type = diagnostics.pipe(
374+
fromSdkStreamMetadata(sdkContext, streamMetadata),
375+
);
376+
methodInputParameter.location = RequestLocation.Body;
377+
}
356378
parameters.push(methodInputParameter);
357379
continue;
358380
}
@@ -365,6 +387,12 @@ function fromSdkServiceMethodParameters(
365387
rootApiVersions,
366388
diagnostics,
367389
);
390+
if (isStreamingBodyParameter) {
391+
methodInputParameter.type = diagnostics.pipe(
392+
fromSdkStreamMetadata(sdkContext, streamMetadata),
393+
);
394+
methodInputParameter.location = RequestLocation.Body;
395+
}
368396
parameters.push(methodInputParameter);
369397
}
370398

@@ -378,6 +406,15 @@ function updateMethodParameter(
378406
rootApiVersions: string[],
379407
diagnostics: ReturnType<typeof createDiagnosticCollector>,
380408
): void {
409+
if (
410+
operationHttpParameter.kind === "body" &&
411+
isJsonLinesStream(operationHttpParameter.streamMetadata)
412+
) {
413+
methodParameter.type = diagnostics.pipe(
414+
fromSdkStreamMetadata(sdkContext, operationHttpParameter.streamMetadata),
415+
);
416+
}
417+
381418
// for content type parameter
382419
if (isContentType(operationHttpParameter)) {
383420
methodParameter.type = diagnostics.pipe(
@@ -408,7 +445,9 @@ function fromSdkServiceMethodResponse(
408445
const diagnostics = createDiagnosticCollector();
409446

410447
return diagnostics.wrap({
411-
type: diagnostics.pipe(getResponseType(sdkContext, methodResponse.type)),
448+
type: isSupportedStream(methodResponse.streamMetadata)
449+
? diagnostics.pipe(fromSdkStreamMetadata(sdkContext, methodResponse.streamMetadata))
450+
: diagnostics.pipe(getResponseType(sdkContext, methodResponse.type)),
412451
resultSegments: methodResponse.resultSegments?.map((segment) =>
413452
getResponseSegmentName(segment),
414453
),
@@ -607,7 +646,9 @@ function fromBodyParameter(
607646
rootApiVersions: string[],
608647
): [InputBodyParameter, readonly Diagnostic[]] {
609648
const diagnostics = createDiagnosticCollector();
610-
const parameterType = diagnostics.pipe(fromSdkType(sdkContext, p.type, p));
649+
const parameterType = isJsonLinesStream(p.streamMetadata)
650+
? diagnostics.pipe(fromSdkStreamMetadata(sdkContext, p.streamMetadata))
651+
: diagnostics.pipe(fromSdkType(sdkContext, p.type, p));
611652

612653
const retVar: InputBodyParameter = {
613654
kind: "body",
@@ -725,7 +766,9 @@ export function fromSdkHttpOperationResponse(
725766
const range = sdkResponse.statusCodes;
726767
retVar = {
727768
statusCodes: toStatusCodesArray(range),
728-
bodyType: diagnostics.pipe(getResponseType(sdkContext, sdkResponse.type)),
769+
bodyType: isSupportedStream(sdkResponse.streamMetadata)
770+
? diagnostics.pipe(fromSdkStreamMetadata(sdkContext, sdkResponse.streamMetadata))
771+
: diagnostics.pipe(getResponseType(sdkContext, sdkResponse.type)),
729772
headers: diagnostics.pipe(fromSdkServiceResponseHeaders(sdkContext, sdkResponse.headers)),
730773
isErrorResponse:
731774
sdkResponse.type !== undefined && isErrorModel(sdkContext.program, sdkResponse.type.__raw!),
@@ -737,6 +780,70 @@ export function fromSdkHttpOperationResponse(
737780
return diagnostics.wrap(retVar);
738781
}
739782

783+
function fromSdkStreamMetadata(
784+
sdkContext: CSharpEmitterContext,
785+
streamMetadata: SdkStreamMetadata,
786+
): [InputStreamingType, readonly Diagnostic[]] {
787+
const diagnostics = createDiagnosticCollector();
788+
const originalType = streamMetadata.originalType;
789+
const streamKind = getStreamKind(streamMetadata);
790+
compilerAssert(
791+
streamKind !== undefined,
792+
"Stream metadata must have a supported stream kind before it is converted.",
793+
);
794+
let terminalEventType: string | undefined;
795+
let terminalEventValue: string | undefined;
796+
797+
if (streamKind === "sse" && streamMetadata.streamType.__raw?.kind === "Union") {
798+
const eventDefinitions = diagnostics.pipe(
799+
unsafe_getEventDefinitions(sdkContext.program, streamMetadata.streamType.__raw as Union),
800+
);
801+
const terminalDefinition = eventDefinitions.find((definition) =>
802+
isTerminalEvent(sdkContext.program, definition.root),
803+
);
804+
if (terminalDefinition?.payloadType.kind === "String") {
805+
terminalEventType = terminalDefinition.eventType;
806+
terminalEventValue = terminalDefinition.payloadType.value;
807+
}
808+
}
809+
810+
return diagnostics.wrap({
811+
kind: "streaming",
812+
name: originalType.kind === "model" ? originalType.name : "Stream",
813+
valueType: diagnostics.pipe(fromSdkType(sdkContext, streamMetadata.streamType)),
814+
streamKind,
815+
contentTypes: streamMetadata.contentTypes,
816+
terminalEventType,
817+
terminalEventValue,
818+
crossLanguageDefinitionId:
819+
originalType.kind === "model" ? originalType.crossLanguageDefinitionId : "",
820+
});
821+
}
822+
823+
function getStreamKind(
824+
streamMetadata: SdkStreamMetadata | undefined,
825+
): InputStreamingType["streamKind"] | undefined {
826+
if (streamMetadata?.contentTypes.includes("application/jsonl")) {
827+
return "jsonl";
828+
}
829+
if (streamMetadata?.contentTypes.includes("text/event-stream")) {
830+
return "sse";
831+
}
832+
return undefined;
833+
}
834+
835+
function isSupportedStream(
836+
streamMetadata: SdkStreamMetadata | undefined,
837+
): streamMetadata is SdkStreamMetadata {
838+
return getStreamKind(streamMetadata) !== undefined;
839+
}
840+
841+
function isJsonLinesStream(
842+
streamMetadata: SdkStreamMetadata | undefined,
843+
): streamMetadata is SdkStreamMetadata {
844+
return getStreamKind(streamMetadata) === "jsonl";
845+
}
846+
740847
function fromSdkServiceResponseHeaders(
741848
sdkContext: CSharpEmitterContext,
742849
headers: SdkServiceResponseHeader[],

packages/http-client-csharp/emitter/src/type/input-type.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export type InputType =
7979
| InputEnumType
8080
| InputEnumValueType
8181
| InputArrayType
82+
| InputStreamingType
8283
| InputDictionaryType
8384
| InputNullableType;
8485

@@ -305,6 +306,17 @@ export interface InputArrayType extends InputTypeBase {
305306
crossLanguageDefinitionId: string;
306307
}
307308

309+
export interface InputStreamingType extends InputTypeBase {
310+
kind: "streaming";
311+
name: string;
312+
valueType: InputType;
313+
streamKind: "jsonl" | "sse";
314+
contentTypes: string[];
315+
terminalEventType?: string;
316+
terminalEventValue?: string;
317+
crossLanguageDefinitionId: string;
318+
}
319+
308320
export interface InputDictionaryType extends InputTypeBase {
309321
kind: "dict";
310322
keyType: InputType;

0 commit comments

Comments
 (0)