Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,9 @@ export class GeneratedSingleUrlEnvironmentsImpl implements GeneratedEnvironments
referenceToEnvironmentValue: ts.Expression;
baseUrlId: FernIr.EnvironmentBaseUrlId | undefined;
}): ts.Expression {
if (baseUrlId != null) {
throw new Error(
`Cannot get reference to single environment URL because baseUrlId is defined ("${baseUrlId}")`
);
}
// For single URL environments, baseUrlId is irrelevant since there's only one URL.
// This can happen when an AsyncAPI spec defines a named server (e.g. "production")
// which gets converted to a baseUrlId on the WebSocket channel.
return referenceToEnvironmentValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,18 @@ describe("GeneratedSingleUrlEnvironmentsImpl", () => {
expect(getTextOfTsNode(result)).toBe("env");
});

it("getReferenceToEnvironmentUrl throws when baseUrlId is provided", () => {
it("getReferenceToEnvironmentUrl ignores baseUrlId for single URL", () => {
const impl = new GeneratedSingleUrlEnvironmentsImpl({
environmentEnumName: "MyEnvironment",
defaultEnvironmentId: undefined,
environments: singleUrlEnvironments
});
const inputExpr = ts.factory.createIdentifier("env");
expect(() =>
impl.getReferenceToEnvironmentUrl({
referenceToEnvironmentValue: inputExpr,
baseUrlId: "some-base-url"
})
).toThrow();
const result = impl.getReferenceToEnvironmentUrl({
referenceToEnvironmentValue: inputExpr,
baseUrlId: "some-base-url"
});
expect(getTextOfTsNode(result)).toBe("env");
});

it("writeToFile generates environment const and type alias", () => {
Expand Down
12 changes: 12 additions & 0 deletions generators/typescript/sdk/versions.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# yaml-language-server: $schema=../../../fern-versions-yml.schema.json
- version: 3.56.3
changelogEntry:
- summary: |
Fix TypeScript SDK generator crash when generating WebSocket clients for
AsyncAPI specs that define a named server (e.g. `servers.production`) with
a single-URL environment. The `baseUrlId` assigned by the Fern IR converter
is now silently ignored for single-URL environments since there is only one
URL to resolve to.
type: fix
createdAt: "2026-03-16"
irVersion: 65

- version: 3.56.2
changelogEntry:
- summary: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"type": "string",
},
},
"url": "production",
"url": undefined,
},
"types": {
"UsersUserIdMessagesPublish": {
Expand Down Expand Up @@ -72,7 +72,6 @@
},
"rawContents": "channel:
path: /users/{id}/messages
url: production
auth: false
path-parameters:
id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,14 @@
},
"model": "string",
},
"url": "production",
"url": undefined,
},
"imports": {
"root": "__package__.yml",
},
},
"rawContents": "channel:
path: /v1/ws/chat
url: production
auth: false
docs: Chat channel for testing message references
query-parameters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,14 @@
},
},
"path": "/v1/ws/chat",
"url": "production",
"url": undefined,
},
"imports": {
"root": "__package__.yml",
},
},
"rawContents": "channel:
path: /v1/ws/chat
url: production
auth: false
connect-method-name: createChatConnection
docs: Chat channel for testing custom method names
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ export function buildChannel({
declarationFile: RelativeFilePath;
}): void {
const firstServer = channel.servers[0];
// Don't set a urlId when it would result in a single-URL environment.
// This happens when there are only WebSocket servers (no HTTP servers) and only one
// WebSocket server — buildEnvironments creates a single-URL environment in that case,
// so a baseUrlId on the channel would be meaningless and can cause generator issues.
const hasSingleWebsocketServerOnly = context.ir.servers.length === 0 && context.ir.websocketServers.length <= 1;
// Generate URL ID based on feature flag:
// - If groupEnvironmentsByHost is enabled, look up the collision-aware URL ID from the map
// - Otherwise, use simple server name for backward compatibility
// - Skip entirely for single-WebSocket-server-only specs (no multi-URL environment)
const urlId =
firstServer != null
firstServer != null && !hasSingleWebsocketServerOnly
? context.options.groupEnvironmentsByHost
? (context.getUrlId(firstServer.url) ?? generateWebsocketUrlId(firstServer.name, firstServer.url, true))
: firstServer.name
Expand Down
Loading