diff --git a/packages/typespec-ts/src/framework/hooks/binder.ts b/packages/typespec-ts/src/framework/hooks/binder.ts index a1137e62d0..075f0544a5 100644 --- a/packages/typespec-ts/src/framework/hooks/binder.ts +++ b/packages/typespec-ts/src/framework/hooks/binder.ts @@ -50,7 +50,6 @@ class BinderImp implements Binder { private project: Project; private dependencies: Record; private staticHelpers: Map; - private useSubpathImports: boolean; constructor(project: Project, options: BinderOptions = {}) { this.project = project; @@ -58,7 +57,6 @@ class BinderImp implements Binder { provideDependencies(options.dependencies); this.staticHelpers = options.staticHelpers ?? new Map(); this.dependencies = useDependencies(); - this.useSubpathImports = options.useSubpathImports ?? false; } trackDeclaration(refkey: unknown, name: string, sourceFile: SourceFile): string { @@ -185,27 +183,6 @@ class BinderImp implements Binder { return importSpecifier; } - /** - * Returns the #platform/ subpath import specifier for a static helper file - * that has a polyfill variant (-browser.mts or -react-native.mts sibling), - * or undefined if subpath imports are disabled or no variant exists. - * e.g. "src/static-helpers/serialization/get-binary-response.ts" - * -> "#platform/static-helpers/serialization/get-binary-response" - */ - private getPlatformImportSpecifier(declarationSourceFile: SourceFile): string | undefined { - if (!this.useSubpathImports) return undefined; - const filePath = declarationSourceFile.getFilePath(); - const srcIndex = filePath.indexOf("/src/"); - if (srcIndex === -1) return undefined; - // Check if a -browser.mts or -react-native.mts sibling exists - const basePath = filePath.replace(/\.ts$/, ""); - const hasBrowserVariant = this.project.getSourceFile(basePath + "-browser.mts"); - const hasReactNativeVariant = this.project.getSourceFile(basePath + "-react-native.mts"); - if (!hasBrowserVariant && !hasReactNativeVariant) return undefined; - const relativePath = filePath.substring(srcIndex + "/src/".length); - return "#platform/" + relativePath.replace(/\.ts$/, ""); - } - /** * Applies all tracked imports to their respective source files. */ @@ -316,9 +293,7 @@ class BinderImp implements Binder { if (file !== declarationSourceFile) { this.trackReference(declarationKey, file); - // Use #platform/ subpath import specifier for static helpers in warp packages - const platformSpecifier = this.getPlatformImportSpecifier(declarationSourceFile); - const importTarget = platformSpecifier ?? declarationSourceFile; + const importTarget = declarationSourceFile; const importDec = this.addImport(file, importTarget, name); name = importDec.alias ?? name; } diff --git a/packages/typespec-ts/src/framework/load-static-helpers.ts b/packages/typespec-ts/src/framework/load-static-helpers.ts index 6d18b92214..2351f58959 100644 --- a/packages/typespec-ts/src/framework/load-static-helpers.ts +++ b/packages/typespec-ts/src/framework/load-static-helpers.ts @@ -13,6 +13,7 @@ import { ModularEmitterOptions } from "../modular/interfaces.js"; import { resolveProjectRoot } from "../utils/resolve-project-root.js"; import { refkey } from "./refkey.js"; export const SourceFileSymbol = Symbol("SourceFile"); + export interface StaticHelperMetadata { name: string; kind: "function" | "interface" | "typeAlias" | "class" | "enum"; @@ -95,10 +96,10 @@ export async function loadStaticHelpers( overwrite: true, }); addedFile.getImportDeclarations().map((i) => { - // Rewrite relative platform-types imports to #platform/ specifiers - // so that browser/react-native variants are resolved via subpath imports. - // Only rewrite imports to the default variant (not -browser/-react-native variants - // which are already platform-specific direct imports). + // Rewrite relative platform-types imports to @azure/core-rest-pipeline for azure packages + // (NodeReadableStream is now exported directly from @azure/core-rest-pipeline). + // Non-azure packages keep the relative import to the local platform-types.ts. + const specifier = i.getModuleSpecifierValue(); if ( specifier.startsWith(".") && @@ -106,10 +107,9 @@ export async function loadStaticHelpers( !specifier.includes("-browser") && !specifier.includes("-react-native") ) { - i.setModuleSpecifier("#platform/static-helpers/platform-types"); + i.setModuleSpecifier("@azure/core-rest-pipeline"); } }); - for (const entry of Object.values(helpers)) { if (!addedFile.getFilePath().endsWith(entry.location)) { continue; diff --git a/packages/typespec-ts/src/index.ts b/packages/typespec-ts/src/index.ts index 469b215404..af4c494f5c 100644 --- a/packages/typespec-ts/src/index.ts +++ b/packages/typespec-ts/src/index.ts @@ -23,7 +23,6 @@ import { CreateRecorderHelpers, MultipartHelpers, PagingHelpers, - PlatformTypeHelpers, PollingHelpers, SerializationHelpers, SimplePollerHelpers, @@ -75,7 +74,7 @@ import { import { Project } from "ts-morph"; import { provideBinder } from "./framework/hooks/binder.js"; import { provideSdkTypes } from "./framework/hooks/sdk-types.js"; -import { loadStaticHelpers } from "./framework/load-static-helpers.js"; +import { loadStaticHelpers, type StaticHelpers } from "./framework/load-static-helpers.js"; import { EmitterOptions } from "./lib.js"; import { buildClassicalClient } from "./modular/build-classical-client.js"; import { buildClassicOperationFiles } from "./modular/build-classical-operation-groups.js"; @@ -148,12 +147,11 @@ export async function $onEmit(context: EmitContext) { ...SimplePollerHelpers, ...UrlTemplateHelpers, ...MultipartHelpers, - ...PlatformTypeHelpers, ...CloudSettingHelpers, ...XmlHelpers, ...(rlcOptions.generateTest ? CreateRecorderHelpers : {}), ...(rlcOptions.enableStorageCompat ? StorageCompatHelpers : {}), - }, + } as unknown as StaticHelpers, { sourcesDir: dpgContext.generationPathDetail?.modularSourcesDir, rootDir: dpgContext.generationPathDetail?.rootDir, @@ -174,7 +172,6 @@ export async function $onEmit(context: EmitContext) { dependencies: { ...extraDependencies, }, - useSubpathImports: true, }); provideSdkTypes(dpgContext); diff --git a/packages/typespec-ts/src/modular/build-root-index.ts b/packages/typespec-ts/src/modular/build-root-index.ts index 07fcb5482e..5942171d01 100644 --- a/packages/typespec-ts/src/modular/build-root-index.ts +++ b/packages/typespec-ts/src/modular/build-root-index.ts @@ -9,15 +9,11 @@ import { getModularClientOptions } from "../utils/client-utils.js"; import { SdkContext } from "../utils/interfaces.js"; import { getMethodHierarchiesMap } from "../utils/operation-util.js"; import { partitionAndEmitExports } from "./build-subpath-index.js"; +import { AzureCoreDependencies } from "./external-dependencies.js"; import { getClassicalClientName } from "./helpers/naming-helpers.js"; import { isLroOnlyOperation } from "./helpers/operation-helpers.js"; import { ModularEmitterOptions } from "./interfaces.js"; -import { - CloudSettingHelpers, - MultipartHelpers, - PagingHelpers, - PlatformTypeHelpers, -} from "./static-helpers-metadata.js"; +import { CloudSettingHelpers, MultipartHelpers, PagingHelpers } from "./static-helpers-metadata.js"; export function buildRootIndex( context: SdkContext, @@ -157,7 +153,7 @@ function exportFileContentsType(context: SdkContext, rootIndexFile: SourceFile) rootIndexFile, [ resolveReference(MultipartHelpers.FileContents), - resolveReference(PlatformTypeHelpers.NodeReadableStream), + resolveReference(AzureCoreDependencies["NodeReadableStream"]), ], true, ); diff --git a/packages/typespec-ts/src/modular/external-dependencies.ts b/packages/typespec-ts/src/modular/external-dependencies.ts index da36ad7c12..d7492dc7fd 100644 --- a/packages/typespec-ts/src/modular/external-dependencies.ts +++ b/packages/typespec-ts/src/modular/external-dependencies.ts @@ -207,6 +207,16 @@ export const AzureCoreDependencies: CoreDependencies = { name: "ErrorResponse", module: "@azure-rest/core-client", }, + getBinaryStreamResponse: { + kind: "externalDependency", + module: "@azure-rest/core-client", + name: "getBinaryStreamResponse", + }, + NodeReadableStream: { + kind: "externalDependency", + module: "@azure/core-rest-pipeline", + name: "NodeReadableStream", + }, }; export const AzureIdentityDependencies = { diff --git a/packages/typespec-ts/src/modular/helpers/operation-helpers.ts b/packages/typespec-ts/src/modular/helpers/operation-helpers.ts index 0f474c2f65..15c17d8d77 100644 --- a/packages/typespec-ts/src/modular/helpers/operation-helpers.ts +++ b/packages/typespec-ts/src/modular/helpers/operation-helpers.ts @@ -48,7 +48,7 @@ import { KnownCollectionFormat, ServiceOperation, } from "../../utils/operation-util.js"; -import { AzurePollingDependencies } from "../external-dependencies.js"; +import { AzureCoreDependencies, AzurePollingDependencies } from "../external-dependencies.js"; import { buildModelDeserializer, buildPropertyDeserializer, @@ -70,7 +70,6 @@ import { } from "../serialization/serialize-utils.js"; import { PagingHelpers, - PlatformTypeHelpers, PollingHelpers, SerializationHelpers, StorageCompatHelpers, @@ -1043,7 +1042,7 @@ export function getOperationFunction( statements.push(`const ${streamableMethodVarName} = _${name}Send(${sendParameterList});`); const binaryHelper = wrapReturn && wrapReturnIsBinary - ? SerializationHelpers.getBinaryStreamResponse + ? AzureCoreDependencies["getBinaryStreamResponse"] : SerializationHelpers.getBinaryResponse; statements.push( `const ${resultVarName} = await ${resolveReference(binaryHelper)}(${streamableMethodVarName});`, @@ -3003,7 +3002,7 @@ export function buildNonModelResponseTypeDeclaration( let typeBody: string; if (isBinary) { - const nodeReadableStreamRef = resolveReference(PlatformTypeHelpers.NodeReadableStream); + const nodeReadableStreamRef = resolveReference(AzureCoreDependencies["NodeReadableStream"]); typeBody = `{ /** * BROWSER ONLY diff --git a/packages/typespec-ts/src/modular/static-helpers-metadata.ts b/packages/typespec-ts/src/modular/static-helpers-metadata.ts index fdb7821057..1736683424 100644 --- a/packages/typespec-ts/src/modular/static-helpers-metadata.ts +++ b/packages/typespec-ts/src/modular/static-helpers-metadata.ts @@ -59,11 +59,6 @@ export const SerializationHelpers = { name: "getBinaryResponse", location: "serialization/get-binary-response.ts", }, - getBinaryStreamResponse: { - kind: "function", - name: "getBinaryStreamResponse", - location: "serialization/get-binary-stream-response.ts", - }, areAllPropsUndefined: { kind: "function", name: "areAllPropsUndefined", @@ -150,14 +145,6 @@ export const MultipartHelpers = { }, } as const; -export const PlatformTypeHelpers = { - NodeReadableStream: { - kind: "typeAlias", - name: "NodeReadableStream", - location: "platform-types.ts", - }, -} as const; - export const CloudSettingHelpers = { AzureClouds: { kind: "enum", diff --git a/packages/typespec-ts/src/rlc-common/metadata/build-package-file.ts b/packages/typespec-ts/src/rlc-common/metadata/build-package-file.ts index 34dd7f0df7..61e38786d8 100644 --- a/packages/typespec-ts/src/rlc-common/metadata/build-package-file.ts +++ b/packages/typespec-ts/src/rlc-common/metadata/build-package-file.ts @@ -131,9 +131,6 @@ export function updatePackageFile( // Update Core Client dependency if (needsCoreClientUpdate) { delete deps["@azure/core-client"]; - if (!("@azure-rest/core-client" in deps)) { - deps["@azure-rest/core-client"] = "^2.3.1"; - } packageInfo.dependencies = deps; } @@ -146,6 +143,12 @@ export function updatePackageFile( }; } + packageInfo.dependencies = { + ...packageInfo.dependencies, + "@azure/core-rest-pipeline": "^1.24.0", + "@azure-rest/core-client": "^2.7.0", + }; + // Update constantPaths metadata for Azure packages if (needsConstantPathsUpdate && packageInfo["//metadata"]) { const metadata = packageInfo["//metadata"]; diff --git a/packages/typespec-ts/src/rlc-common/metadata/package-json/build-azure-monorepo-package.ts b/packages/typespec-ts/src/rlc-common/metadata/package-json/build-azure-monorepo-package.ts index 46e154eb60..ff50a99975 100644 --- a/packages/typespec-ts/src/rlc-common/metadata/package-json/build-azure-monorepo-package.ts +++ b/packages/typespec-ts/src/rlc-common/metadata/package-json/build-azure-monorepo-package.ts @@ -32,7 +32,7 @@ export function getAzureMonorepoDependencies(config: AzureMonorepoInfoConfig) { // revert this change after sdk repo update. const runtimeDeps = { ...dependencies, - "@azure-rest/core-client": "^2.3.1", + "@azure-rest/core-client": "^2.7.0", ...(hasLro && { "@azure/abort-controller": "^2.1.2", }), @@ -40,7 +40,7 @@ export function getAzureMonorepoDependencies(config: AzureMonorepoInfoConfig) { ...(hasLro && { "@azure/core-lro": "^3.1.0", }), - "@azure/core-rest-pipeline": "^1.20.0", + "@azure/core-rest-pipeline": "^1.24.0", "@azure/core-util": "^1.12.0", "@azure/logger": "^1.2.0", tslib: "^2.8.1", diff --git a/packages/typespec-ts/src/rlc-common/metadata/package-json/package-common.ts b/packages/typespec-ts/src/rlc-common/metadata/package-json/package-common.ts index 32483bc909..14520bc8cd 100644 --- a/packages/typespec-ts/src/rlc-common/metadata/package-json/package-common.ts +++ b/packages/typespec-ts/src/rlc-common/metadata/package-json/package-common.ts @@ -45,26 +45,11 @@ function getEntryPointInformation(config: PackageCommonInfoConfig) { module: "./dist/esm/index.js", types: "./dist/commonjs/index.d.ts", browser: "./dist/browser/index.js", - imports: { - "#platform/*": { - browser: "./src/*-browser.mts", - default: "./src/*.ts", - } as Record, - }, exports: resolveWarpExports(config.exports, config.generateReactNativeTarget), }; if (config.generateReactNativeTarget) { result["react-native"] = "./dist/react-native/index.js"; - (result["imports"]["#platform/*"] as Record)["react-native"] = - "./src/*-react-native.mts"; - // Reorder so react-native comes before default - const importsEntry = result["imports"]["#platform/*"] as Record; - result["imports"]["#platform/*"] = { - browser: importsEntry["browser"], - "react-native": importsEntry["react-native"], - default: importsEntry["default"], - }; } return result; diff --git a/packages/typespec-ts/static/static-helpers/platform-types-browser.mts b/packages/typespec-ts/static/static-helpers/platform-types-browser.mts deleted file mode 100644 index 6b6410ced0..0000000000 --- a/packages/typespec-ts/static/static-helpers/platform-types-browser.mts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Browser platform variant — NodeReadableStream resolves to `never` - * so it drops out of union types and optional properties become effectively absent. - */ -export type NodeReadableStream = never; diff --git a/packages/typespec-ts/static/static-helpers/platform-types-react-native.mts b/packages/typespec-ts/static/static-helpers/platform-types-react-native.mts deleted file mode 100644 index e13cb8e69b..0000000000 --- a/packages/typespec-ts/static/static-helpers/platform-types-react-native.mts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * React Native platform variant — NodeReadableStream resolves to `never` - * so it drops out of union types and optional properties become effectively absent. - */ -export type NodeReadableStream = never; diff --git a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-browser.mts b/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-browser.mts deleted file mode 100644 index dbdf3faf77..0000000000 --- a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-browser.mts +++ /dev/null @@ -1,22 +0,0 @@ -import { HttpResponse, StreamableMethod } from "@azure-rest/core-client"; -import { NodeReadableStream } from "../platform-types-browser.mjs"; - -/** - * Resolves a StreamableMethod into a binary stream response using browser streaming. - * Returns both the raw HttpResponse (for status/header inspection) and a blobBody Promise. - * Error handling is left to the caller so that generated deserializers can apply - * operation-specific error deserialization (per-status-code details, exception headers, etc.). - */ -export async function getBinaryStreamResponse(streamableMethod: StreamableMethod): Promise< - HttpResponse & { - blobBody?: Promise; - readableStreamBody?: NodeReadableStream; - } -> { - const response = await streamableMethod.asBrowserStream(); - return { - ...response, - blobBody: new Response(response.body).blob(), - readableStreamBody: undefined, - }; -} diff --git a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-react-native.mts b/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-react-native.mts deleted file mode 100644 index d30a405be6..0000000000 --- a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response-react-native.mts +++ /dev/null @@ -1 +0,0 @@ -export { getBinaryStreamResponse } from "./get-binary-stream-response-browser.mjs"; diff --git a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response.ts b/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response.ts deleted file mode 100644 index ff37e55031..0000000000 --- a/packages/typespec-ts/static/static-helpers/serialization/get-binary-stream-response.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { HttpResponse, StreamableMethod } from "@azure-rest/core-client"; -import { NodeReadableStream } from "../platform-types.js"; - -/** - * Resolves a StreamableMethod into a binary stream response using Node.js streaming. - * Returns both the raw HttpResponse (for status/header inspection) and the readable stream body. - * Error handling is left to the caller so that generated deserializers can apply - * operation-specific error deserialization (per-status-code details, exception headers, etc.). - */ -export async function getBinaryStreamResponse(streamableMethod: StreamableMethod): Promise< - HttpResponse & { - blobBody?: Promise; - readableStreamBody?: NodeReadableStream; - } -> { - const response = await streamableMethod.asNodeStream(); - return { - ...response, - blobBody: undefined, - readableStreamBody: response.body, - }; -} diff --git a/packages/typespec-ts/test-next/integration/load-static-files.test.ts b/packages/typespec-ts/test-next/integration/load-static-files.test.ts index cb1b4df434..8b80208e86 100644 --- a/packages/typespec-ts/test-next/integration/load-static-files.test.ts +++ b/packages/typespec-ts/test-next/integration/load-static-files.test.ts @@ -73,7 +73,7 @@ describe("loadStaticHelpers", () => { ).rejects.toThrowError(/invalid helper kind/); }); - it("should rewrite platform-types imports to #platform subpath without extension", async () => { + it("should rewrite platform-types imports to @azure/core-rest-pipeline for azure monorepo", async () => { const helpers = { usesPlatformImport: { kind: "function", @@ -91,7 +91,7 @@ describe("loadStaticHelpers", () => { .getSourceFiles() .find((file) => file.getFilePath().endsWith("/static-helpers/platform-import.ts")); assert(sourceFile); - const importDecl = sourceFile.getImportDeclaration("#platform/static-helpers/platform-types"); + const importDecl = sourceFile.getImportDeclaration("@azure/core-rest-pipeline"); expect(importDecl).toBeDefined(); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0b8ee9c38..ca73224c56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,7 +40,7 @@ catalogs: specifier: ^0.40.0 version: 0.40.0 '@azure-rest/core-client': - specifier: ^2.3.1 + specifier: ^2.7.0 version: 2.7.0 '@azure/abort-controller': specifier: ^2.1.2 @@ -55,7 +55,7 @@ catalogs: specifier: ^1.5.0 version: 1.6.2 '@azure/core-rest-pipeline': - specifier: ^1.14.0 + specifier: ^1.24.0 version: 1.24.0 '@azure/core-util': specifier: ^1.4.0 @@ -20613,7 +20613,7 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 24.13.2 + '@types/node': 26.0.0 '@types/semver@7.7.1': {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d09806a4db..16f55e0358 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -35,12 +35,12 @@ catalog: "@astrojs/check": ^0.9.8 "@astrojs/react": ^6.0.0 "@astrojs/starlight": ^0.40.0 - "@azure-rest/core-client": ^2.3.1 + "@azure-rest/core-client": ^2.7.0 "@azure/abort-controller": ^2.1.2 "@azure/core-auth": ^1.6.0 "@azure/core-lro": ^3.1.0 "@azure/core-paging": ^1.5.0 - "@azure/core-rest-pipeline": ^1.14.0 + "@azure/core-rest-pipeline": ^1.24.0 "@azure/core-util": ^1.4.0 "@azure/identity": ^4.13.1 "@azure/logger": ^1.0.4