From 6096940a9b082f837df4eabc8189a618064e301f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 17:57:47 +0000 Subject: [PATCH 1/2] Initial plan From 89e1918a4cdb17f49126701c0db7e4be9d1678ef Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:10:37 +0000 Subject: [PATCH 2/2] fix: replace NodeJS.ReadableStream with NodeReadableStream from #platform/ import in RLC generated code Replace inline NodeJS.ReadableStream type references with NodeReadableStream imported from platform-types static helper. This uses the #platform/ subpath import pattern (for azureSdkForJs) so that browser builds resolve to `never` and Node builds resolve to the actual NodeJS.ReadableStream type. Agent-Logs-Url: https://github.com/Azure/autorest.typescript/sessions/197375da-5572-4d2b-9001-6e387e9f043d Co-authored-by: jeremymeng <7583839+jeremymeng@users.noreply.github.com> --- packages/rlc-common/src/buildObjectTypes.ts | 4 +-- .../rlc-common/src/buildParameterTypes.ts | 19 ++++++++++ packages/rlc-common/src/buildSchemaType.ts | 20 +++++++++++ packages/typespec-ts/src/utils/modelUtils.ts | 2 +- .../test/unit/bytesGenerator.spec.ts | 35 ++++++++++++------- 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/packages/rlc-common/src/buildObjectTypes.ts b/packages/rlc-common/src/buildObjectTypes.ts index 89a7c381b2..cbe7d3fdf6 100644 --- a/packages/rlc-common/src/buildObjectTypes.ts +++ b/packages/rlc-common/src/buildObjectTypes.ts @@ -586,8 +586,8 @@ function getPropertySignatures( function isBinaryArray(schema: Schema): boolean { return Boolean( isArraySchema(schema) && - (schema.items?.typeName?.includes("NodeJS.ReadableStream") || - schema.items?.outputTypeName?.includes("NodeJS.ReadableStream")) + (schema.items?.typeName?.includes("NodeReadableStream") || + schema.items?.outputTypeName?.includes("NodeReadableStream")) ); } diff --git a/packages/rlc-common/src/buildParameterTypes.ts b/packages/rlc-common/src/buildParameterTypes.ts index f5f2f446e5..326a083dae 100644 --- a/packages/rlc-common/src/buildParameterTypes.ts +++ b/packages/rlc-common/src/buildParameterTypes.ts @@ -181,6 +181,25 @@ export function buildParameterTypes(model: RLCModel) { } ]); } + // Add NodeReadableStream import if binary types are used in parameters + if (parametersFile.getFullText().includes("NodeReadableStream")) { + const platformTypesModuleSpecifier = model.options?.azureSdkForJs + ? "#platform/static-helpers/platform-types.js" + : getImportModuleName( + { + cjsName: `./static-helpers/platform-types`, + esModulesName: `./static-helpers/platform-types.js` + }, + model + ); + parametersFile.addImportDeclarations([ + { + isTypeOnly: true, + namedImports: ["NodeReadableStream"], + moduleSpecifier: platformTypesModuleSpecifier + } + ]); + } return { path: filePath, content: parametersFile.getFullText() }; } diff --git a/packages/rlc-common/src/buildSchemaType.ts b/packages/rlc-common/src/buildSchemaType.ts index b4ffa3b1b3..4aafc0907c 100644 --- a/packages/rlc-common/src/buildSchemaType.ts +++ b/packages/rlc-common/src/buildSchemaType.ts @@ -10,6 +10,7 @@ import { } from "./buildObjectTypes.js"; import { RLCModel, SchemaContext } from "./interfaces.js"; import { getImportSpecifier } from "./helpers/importsUtil.js"; +import { getImportModuleName } from "./helpers/nameConstructors.js"; /** * Generates types to represent schema definitions in the swagger @@ -75,6 +76,25 @@ export function generateModelFiles( } ]); } + // Add NodeReadableStream import if binary types are used in models + if (modelsFile.getFullText().includes("NodeReadableStream")) { + const platformTypesModuleSpecifier = model.options?.azureSdkForJs + ? "#platform/static-helpers/platform-types.js" + : getImportModuleName( + { + cjsName: `./static-helpers/platform-types`, + esModulesName: `./static-helpers/platform-types.js` + }, + model + ); + modelsFile.addImportDeclarations([ + { + isTypeOnly: true, + namedImports: ["NodeReadableStream"], + moduleSpecifier: platformTypesModuleSpecifier + } + ]); + } return { path: filePath, content: modelsFile.getFullText() }; } return undefined; diff --git a/packages/typespec-ts/src/utils/modelUtils.ts b/packages/typespec-ts/src/utils/modelUtils.ts index 71cbcebf46..2fbb5b5e75 100644 --- a/packages/typespec-ts/src/utils/modelUtils.ts +++ b/packages/typespec-ts/src/utils/modelUtils.ts @@ -85,7 +85,7 @@ import { getModelNamespaceName } from "./namespaceUtils.js"; import { reportDiagnostic } from "../lib.js"; export const BINARY_TYPE_UNION = - "string | Uint8Array | ReadableStream | NodeJS.ReadableStream"; + "string | Uint8Array | ReadableStream | NodeReadableStream"; export const BINARY_AND_FILE_TYPE_UNION = `${BINARY_TYPE_UNION} | File`; diff --git a/packages/typespec-ts/test/unit/bytesGenerator.spec.ts b/packages/typespec-ts/test/unit/bytesGenerator.spec.ts index f459556b09..bb9bb4036b 100644 --- a/packages/typespec-ts/test/unit/bytesGenerator.spec.ts +++ b/packages/typespec-ts/test/unit/bytesGenerator.spec.ts @@ -23,6 +23,7 @@ describe("bytes", () => { parameters?.content!, ` import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface UploadFileViaBodyBodyParam { /** Value may contain any sequence of octets */ @@ -30,7 +31,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream; + | NodeReadableStream; } export interface UploadFileViaBodyMediaTypesParam { @@ -59,6 +60,7 @@ describe("bytes", () => { parameters?.content!, ` import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface UploadFileViaBodyBodyParam { /** Value may contain any sequence of octets */ @@ -66,7 +68,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream; + | NodeReadableStream; } export interface UploadFileViaBodyMediaTypesParam { @@ -118,6 +120,7 @@ describe("bytes", () => { await assertEqualContent( parameters?.content!, `import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface ReadBodyParam { /** Value may contain any sequence of octets */ @@ -125,7 +128,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream; + | NodeReadableStream; } export type ReadParameters = ReadBodyParam & RequestParameters; @@ -188,6 +191,7 @@ describe("bytes", () => { parameters?.content!, ` import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface UploadFileBodyParam { /** Value may contain any sequence of octets */ @@ -201,7 +205,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -212,7 +216,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -250,6 +254,7 @@ describe("bytes", () => { parameters?.content!, ` import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface UploadFileBodyParam { /** Value may contain any sequence of octets */ @@ -263,7 +268,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -274,7 +279,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -359,6 +364,8 @@ describe("bytes", () => { await assertEqualContent( models.inputModelFile?.content!, ` + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; + export interface FooNamePartDescriptor { name: "name"; body: string; @@ -370,7 +377,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -382,7 +389,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -394,7 +401,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File; filename?: string; contentType?: string; @@ -406,7 +413,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream + | NodeReadableStream | File | number; filename?: string; @@ -525,10 +532,11 @@ describe("bytes", () => { ` import type { RequestParameters } from "@azure-rest/core-client"; import type { SchemaContentTypeValues } from "./models.js"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface ReadBodyParam { /** Value may contain any sequence of octets */ - body: string | Uint8Array | ReadableStream | NodeJS.ReadableStream; + body: string | Uint8Array | ReadableStream | NodeReadableStream; } export interface ReadMediaTypesParam { @@ -552,6 +560,7 @@ describe("bytes", () => { parameters?.content!, ` import type { RequestParameters } from "@azure-rest/core-client"; + import type { NodeReadableStream } from "./static-helpers/platform-types.js"; export interface ReadBodyParam { /** Value may contain any sequence of octets */ @@ -559,7 +568,7 @@ describe("bytes", () => { | string | Uint8Array | ReadableStream - | NodeJS.ReadableStream; + | NodeReadableStream; } export interface ReadMediaTypesParam {