From 8ceb74aa3125215ce5c0f8c92f1712f57c59ba3a Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 02:33:16 +0000 Subject: [PATCH 1/3] fix(ts-sdk): use bracket notation for non-identifier property names in file upload requests Co-Authored-By: thomas@buildwithfern.com --- .../FileUploadRequestParameter.ts | 16 ++++++++++++---- generators/typescript/sdk/versions.yml | 10 ++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts b/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts index 814990ead906..f595afbd67f3 100644 --- a/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts +++ b/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts @@ -111,9 +111,17 @@ export class FileUploadRequestParameter extends AbstractRequestParameter { } private getReferenceToProperty(propertyName: string): ts.Expression { - return ts.factory.createPropertyAccessExpression( - ts.factory.createIdentifier(this.getRequestParameterName()), - propertyName - ); + const requestIdentifier = ts.factory.createIdentifier(this.getRequestParameterName()); + if (!this.isValidIdentifier(propertyName)) { + return ts.factory.createElementAccessExpression( + requestIdentifier, + ts.factory.createStringLiteral(propertyName) + ); + } + return ts.factory.createPropertyAccessExpression(requestIdentifier, propertyName); + } + + private isValidIdentifier(name: string): boolean { + return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name); } } diff --git a/generators/typescript/sdk/versions.yml b/generators/typescript/sdk/versions.yml index 2afd1ff373d7..91af566fba58 100644 --- a/generators/typescript/sdk/versions.yml +++ b/generators/typescript/sdk/versions.yml @@ -1,4 +1,14 @@ # yaml-language-server: $schema=../../../fern-versions-yml.schema.json +- version: 3.37.1 + changelogEntry: + - summary: | + Fix file upload request parameters to use bracket notation for property names that are not valid JavaScript identifiers (e.g., header names with hyphens like `X-UIPATH-OrganizationUnitId`). + Previously, the generator produced invalid JavaScript like `request.X - UIPATH - OrganizationUnitId` which was interpreted as subtraction operations. + Now it correctly generates `request["X-UIPATH-OrganizationUnitId"]`. + type: fix + createdAt: "2025-12-08" + irVersion: 62 + - version: 3.37.0 changelogEntry: - summary: | From f01b23308d77744103072370dd3239c9e41c8d9d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 02:48:07 +0000 Subject: [PATCH 2/3] chore: update changelog to use generic header example Co-Authored-By: thomas@buildwithfern.com --- generators/typescript/sdk/versions.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generators/typescript/sdk/versions.yml b/generators/typescript/sdk/versions.yml index 91af566fba58..b5dd40125d4e 100644 --- a/generators/typescript/sdk/versions.yml +++ b/generators/typescript/sdk/versions.yml @@ -2,9 +2,9 @@ - version: 3.37.1 changelogEntry: - summary: | - Fix file upload request parameters to use bracket notation for property names that are not valid JavaScript identifiers (e.g., header names with hyphens like `X-UIPATH-OrganizationUnitId`). - Previously, the generator produced invalid JavaScript like `request.X - UIPATH - OrganizationUnitId` which was interpreted as subtraction operations. - Now it correctly generates `request["X-UIPATH-OrganizationUnitId"]`. + Fix file upload request parameters to use bracket notation for property names that are not valid JavaScript identifiers (e.g., header names with hyphens like `X-Custom-Header`). + Previously, the generator produced invalid JavaScript like `request.X - Custom - Header` which was interpreted as subtraction operations. + Now it correctly generates `request["X-Custom-Header"]`. type: fix createdAt: "2025-12-08" irVersion: 62 From 3b5d788c2f216fa298b11ad87524a28b8c0348e4 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 10 Dec 2025 04:17:44 +0000 Subject: [PATCH 3/3] refactor: use shared isValidIdentifier utility from commons package Co-Authored-By: thomas@buildwithfern.com --- .../src/request-parameter/FileUploadRequestParameter.ts | 8 ++------ .../utils/commons/src/codegen-utils/getPropertyKey.ts | 8 ++++++++ generators/typescript/utils/commons/src/index.ts | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts b/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts index f595afbd67f3..f29808ebee6d 100644 --- a/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts +++ b/generators/typescript/sdk/client-class-generator/src/request-parameter/FileUploadRequestParameter.ts @@ -1,5 +1,5 @@ import { ExampleEndpointCall, HttpHeader, InlinedRequestBodyProperty, QueryParameter } from "@fern-fern/ir-sdk/api"; -import { GetReferenceOpts } from "@fern-typescript/commons"; +import { GetReferenceOpts, isValidIdentifier } from "@fern-typescript/commons"; import { GeneratedRequestWrapper, SdkContext } from "@fern-typescript/contexts"; import { ts } from "ts-morph"; @@ -112,7 +112,7 @@ export class FileUploadRequestParameter extends AbstractRequestParameter { private getReferenceToProperty(propertyName: string): ts.Expression { const requestIdentifier = ts.factory.createIdentifier(this.getRequestParameterName()); - if (!this.isValidIdentifier(propertyName)) { + if (!isValidIdentifier(propertyName)) { return ts.factory.createElementAccessExpression( requestIdentifier, ts.factory.createStringLiteral(propertyName) @@ -120,8 +120,4 @@ export class FileUploadRequestParameter extends AbstractRequestParameter { } return ts.factory.createPropertyAccessExpression(requestIdentifier, propertyName); } - - private isValidIdentifier(name: string): boolean { - return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name); - } } diff --git a/generators/typescript/utils/commons/src/codegen-utils/getPropertyKey.ts b/generators/typescript/utils/commons/src/codegen-utils/getPropertyKey.ts index 55358697fc74..34b5f50816d9 100644 --- a/generators/typescript/utils/commons/src/codegen-utils/getPropertyKey.ts +++ b/generators/typescript/utils/commons/src/codegen-utils/getPropertyKey.ts @@ -1,5 +1,13 @@ import esutils from "esutils"; +/** + * Checks if a string is a valid JavaScript/TypeScript identifier name. + * This can be used to determine whether to use dot notation (obj.prop) or bracket notation (obj["prop"]). + */ +export function isValidIdentifier(name: string): boolean { + return esutils.keyword.isIdentifierNameES6(name); +} + export function getPropertyKey(key: string): string { // [key: string]: any; => [key: string]: any; if (key.startsWith("[") && key.endsWith("]")) { diff --git a/generators/typescript/utils/commons/src/index.ts b/generators/typescript/utils/commons/src/index.ts index e0bd50858eb2..8a9cd783d0ad 100644 --- a/generators/typescript/utils/commons/src/index.ts +++ b/generators/typescript/utils/commons/src/index.ts @@ -9,7 +9,7 @@ export { getParameterNameForRootExamplePathParameter, getParameterNameForRootPathParameter } from "./codegen-utils/getParameterNameForPathParameter"; -export { getPropertyKey } from "./codegen-utils/getPropertyKey"; +export { getPropertyKey, isValidIdentifier } from "./codegen-utils/getPropertyKey"; export { getSchemaOptions } from "./codegen-utils/getSchemaOptions"; export { getSdkParameterPropertyName } from "./codegen-utils/getSdkParameterPropertyName"; export { getTextOfTsKeyword } from "./codegen-utils/getTextOfTsKeyword";