Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript Client Emitter Incorrectly Generates Browser Code with Direct Module Imports and Missing getClient Implementation #2974

Open
mario-guerra opened this issue Dec 31, 2024 · 5 comments
Assignees

Comments

@mario-guerra
Copy link
Member

The TypeSpec TypeScript client code emitter generates browser-specific output (located in the dist/browser directory) that incorrectly includes direct imports from the @typespec/ts-http-runtime module, rather than bundling or replacing these imports with browser-compatible code.

Detailed Description:

When generating a TypeScript client using TypeSpec, the emitter produces a dist/browser directory intended for browser usage. However, the generated JavaScript files within this directory still contain direct imports from the @typespec/ts-http-runtime module, such as:

import { getClient } from "@typespec/ts-http-runtime";

This is incorrect because:

  • Browser Environments: Browsers cannot directly load Node.js modules like @typespec/ts-http-runtime.
  • dist/browser Purpose: The dist/browser output is intended to be a self-contained bundle that does not rely on external Node.js modules at runtime.
  • Incorrect Bundling: The emitter should either bundle the relevant parts of @typespec/ts-http-runtime directly into the dist/browser output or replace the import with a reference to a browser-specific implementation of getClient that's already included in the bundle.

Steps to Reproduce:

  1. Create a TypeSpec project with a service definition that uses HTTP operations.
  2. Use the TypeSpec TypeScript client emitter to generate code.
  3. Examine the generated code in the dist/browser directory, for example anything that uses a client to interact with an API.
  4. Observe the direct imports from @typespec/ts-http-runtime.

Environment:

  • TypeSpec version: 0.63
  • TypeScript client emitter version: 0.37.0
  • Operating System: Windows 11
  • Node.js version: 18.19.0

Additional Information:

  • The package.json for @typespec/ts-http-runtime correctly specifies a browser entry point in the "browser" field.
  • The tshy build process is configured to generate browser-specific output, but the generated code still contains the direct imports and lacks the getClient implementation.
  • There is no apparent configuration option in tspconfig.yaml to specify that a browser client is desired.
@mario-guerra
Copy link
Member Author

@allenjzhang for awareness

@qiaozha
Copy link
Member

qiaozha commented Jan 2, 2025

It sounds like a tshy bundle issue instead of codegen issue @mpodwysocki might have some thoughts here?

@mario-guerra
Copy link
Member Author

mario-guerra commented Jan 2, 2025

@qiaozha maybe, I'm not familiar enough with how the various pieces work to say for sure, but I do see direct import statements in the generated code prior to building the client, see the last line in the code snippet below.

Can tshy account for this somehow?

import {
  GetProjects200Response,
  CreateProject201Response,
  GetProject200Response,
  GetProjectDefaultResponse,
  UpdateProject200Response,
  DeleteProject204Response,
  GetCollaborators200Response,
  GetSections200Response,
  CreateSection201Response,
  GetSection200Response,
  UpdateSection200Response,
  DeleteSection204Response,
  GetTodoItems200Response,
  CreateTodoItem201Response,
  GetTodoItem200Response,
  UpdateTodoItem200Response,
  DeleteTodoItem204Response,
  CloseTodoItem204Response,
  ReopenTodoItem204Response,
  GetComments200Response,
  CreateComment201Response,
  GetComment200Response,
  UpdateComment200Response,
  DeleteComment204Response,
  GetPersonalLabels200Response,
  CreateLabel201Response,
  GetPersonalLabel200Response,
  UpdateLabel200Response,
  DeleteLabel204Response,
  GetSharedLabels200Response,
  RenameSharedLabel204Response,
  RemoveSharedLabel204Response,
} from "./responses.js";
import { Client, StreamableMethod } from "@typespec/ts-http-runtime";
...

@MaryGao
Copy link
Member

MaryGao commented Jan 3, 2025

@mario-guerra

TL;DR: we will not bundle all codes into one file in dist/browser folder. To use our generated library in the browser, you need to use a bundler. For details on how to do this, please refer to our bundling documentation.

The long story is we export our browser version code with node conditional exports under folder dist/browser in package.json. Here the browser should be a common known package condition and is expected to be recoginized with popular bounders like webpack. Actually we mention this in our README.md(link) but it seems in unbranded client we didn't populate this information in README file.

"exports": {
    "./package.json": "./package.json",
    ".": {
      "browser": {
        "types": "./dist/browser/index.d.ts",
        "default": "./dist/browser/index.js"
      },
}

You could also find the sample bundle project here, but let us know if any issue you meet!

@mario-guerra
Copy link
Member Author

@MaryGao thanks for the link. I tried creating a bundle for the generated client code using webpack first, then rollup and I was unsuccessful with either bundler due to numerous errors.

Has anyone been able to successfully create a bundle for unbranded client code generated from TypeSpec?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants