Package
@azure-tools/typespec-ts (RLC emitter)
Summary
For an operation whose request body is bytes, the RLC emitter generates a parameter type that includes NodeJS.ReadableStream. The Azure SDK for JS browser tsconfig sets "types": [] and intentionally excludes @types/node, so the browser compile fails with TS2503: Cannot find namespace 'NodeJS'. Node CJS/ESM targets compile fine; only the browser target fails.
Affected spec / PR
Minimal TypeSpec that triggers it
`model SignedStatement {
@Header("Content-Type")
contentType: "application/cose";
@bodyRoot
body: bytes;
}
@post
@route("/entries")
op createEntry is Foundations.Operation<
SignedStatement & AcceptCoseOrCborHeader,
CreateEntryCreated | CreateEntryPending,
ServiceTraits,
AnyCborError
;`
Generated output (excerpt)
sdk/confidentialledger/codetransparency-rest/src/parameters.ts, line 53:
// Roughly: body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream;
The NodeJS.ReadableStream arm is the offender.
Build error
sdk/confidentialledger/codetransparency-rest/src/parameters.ts(53,60): error TS2503: Cannot find namespace 'NodeJS'. [warp] Build failed for targets: browser ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @azure-rest/codetransparency@1.0.0-beta.1 build
Repro steps
- Use any TypeSpec data-plane operation whose request body is
bytes.
- Run the spec-gen-sdk pipeline (or locally:
pnpm run --filter @azure-rest/<pkg>... build after generation).
- Browser target compilation fails with TS2503 on the generated
parameters.ts.
Expected behavior
The emitter should produce a type union for binary request bodies that compiles in both Node and browser targets. Options:
- Replace
NodeJS.ReadableStream with a structural type like AsyncIterable<Uint8Array>.
- Or split the parameter type across
src/node/ and src/browser/ files selected via the package.json exports node/browser conditions (consistent with how the rest of azure-sdk-for-js isolates Node-only APIs).
Actual behavior
A single parameters.ts with NodeJS.ReadableStream is emitted and consumed by all build targets, breaking the browser build wherever @types/node is excluded (which is repo policy).
Environment
- Emitter:
@azure-tools/typespec-ts (version used by spec-gen-sdk at run time — please confirm from your pipeline; see azure-sdk-for-js lockfile)
- TypeScript: 6.0.3 (per the API Extractor warning in the build log)
- azure-sdk-for-js: HEAD at time of pipeline run
- Repo policy: Browser tsconfigs in azure-sdk-for-js set
"types": [] to exclude @types/node
Workaround used in the spec repo
Added a client.tsp next to the spec narrowing the JS-side type:
@@alternateType(Microsoft.CodeTransparency.SignedStatement.body, string, "javascript");
This unblocks the pipeline but degrades JS ergonomics (callers must pass a base64-encoded string instead of a binary). We would like to remove the workaround once this is fixed upstream.
Impact
Blocks JS SDK generation for any data-plane service with binary request bodies. Other emitters (Python/C#/Java/autorest) are unaffected.
Package
@azure-tools/typespec-ts(RLC emitter)Summary
For an operation whose request body is
bytes, the RLC emitter generates a parameter type that includesNodeJS.ReadableStream. The Azure SDK for JS browser tsconfig sets"types": []and intentionally excludes@types/node, so the browser compile fails with TS2503: Cannot find namespace 'NodeJS'. Node CJS/ESM targets compile fine; only the browser target fails.Affected spec / PR
specification/confidentialledger/Microsoft.CodeTransparencyin Azure/azure-rest-api-specs@azure-rest/codetransparency(sdk/confidentialledger/codetransparency-rest)Minimal TypeSpec that triggers it
`model SignedStatement {
@Header("Content-Type")
contentType: "application/cose";
@bodyRoot
body: bytes;
}
@post
@route("/entries")
op createEntry is Foundations.Operation<
SignedStatement & AcceptCoseOrCborHeader,
CreateEntryCreated | CreateEntryPending,
ServiceTraits,
AnyCborError
Generated output (excerpt)
sdk/confidentialledger/codetransparency-rest/src/parameters.ts, line 53:// Roughly: body: string | Uint8Array | ReadableStream<Uint8Array> | NodeJS.ReadableStream;The
NodeJS.ReadableStreamarm is the offender.Build error
sdk/confidentialledger/codetransparency-rest/src/parameters.ts(53,60): error TS2503: Cannot find namespace 'NodeJS'. [warp] Build failed for targets: browser ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL @azure-rest/codetransparency@1.0.0-beta.1 buildRepro steps
bytes.pnpm run --filter @azure-rest/<pkg>... buildafter generation).parameters.ts.Expected behavior
The emitter should produce a type union for binary request bodies that compiles in both Node and browser targets. Options:
NodeJS.ReadableStreamwith a structural type likeAsyncIterable<Uint8Array>.src/node/andsrc/browser/files selected via thepackage.jsonexportsnode/browserconditions (consistent with how the rest of azure-sdk-for-js isolates Node-only APIs).Actual behavior
A single
parameters.tswithNodeJS.ReadableStreamis emitted and consumed by all build targets, breaking the browser build wherever@types/nodeis excluded (which is repo policy).Environment
@azure-tools/typespec-ts(version used by spec-gen-sdk at run time — please confirm from your pipeline; seeazure-sdk-for-jslockfile)"types": []to exclude@types/nodeWorkaround used in the spec repo
Added a
client.tspnext to the spec narrowing the JS-side type:@@alternateType(Microsoft.CodeTransparency.SignedStatement.body, string, "javascript");This unblocks the pipeline but degrades JS ergonomics (callers must pass a base64-encoded string instead of a binary). We would like to remove the workaround once this is fixed upstream.
Impact
Blocks JS SDK generation for any data-plane service with binary request bodies. Other emitters (Python/C#/Java/autorest) are unaffected.