Skip to content

feat(typescript): add naming configuration object for independent control of class/type names#13545

Merged
fern-support merged 7 commits intomainfrom
devin/1773441614-add-naming-config
Mar 14, 2026
Merged

feat(typescript): add naming configuration object for independent control of class/type names#13545
fern-support merged 7 commits intomainfrom
devin/1773441614-add-naming-config

Conversation

@Swimburger
Copy link
Member

@Swimburger Swimburger commented Mar 13, 2026

Description

Refs: Requested by @Swimburger
Link to Devin Session: https://app.devin.ai/sessions/4ba47fb86534412697f8c6063795cd0c

Adds a new naming configuration to the TypeScript SDK generator that allows users to independently control the namespace export and PascalCase class/type names (client, error, timeout error, environment, environment URLs, version). The existing namespaceExport config continues to work for backwards compatibility.

Supports both a string shorthand and a full object form:

# String shorthand — derives all names via PascalCase
config:
  naming: acme
# Produces: namespace=acme, AcmeClient, AcmeError, AcmeTimeoutError, etc.

# Object form — override individual names
config:
  naming:
    namespace: acme
    client: AcmeSdkClient
    error: AcmeApiError
    environment: AcmeApiEnvironment

When individual overrides are not provided, they are derived from PascalCase(namespace) + suffix (e.g., namespace: "acme"AcmeClient, AcmeError, etc.). When no naming config is present at all, namespaceExport is used as-is for suffix derivation, preserving backwards compatibility (e.g., namespaceExport: "MySDK"MySDKClient).

Changes Made

  • Added NamingConfigSchema to TypescriptCustomConfigSchema.ts as a z.union([string, object]) with 7 optional string fields
  • Added JS identifier validation on naming.namespace and the string shorthand form (rejects invalid identifiers like my-api)
  • Added NamingConfig type (string | NamingObjectConfig) and naming field to SdkCustomConfig
  • Updated getNamespaceExport() to accept naming (string or object) with priority: naming.namespace (or string value) > namespaceExport > default
  • Added resolveNaming() utility that resolves all naming overrides with conditionally PascalCased defaults (PascalCase when naming config is explicitly provided; raw namespaceExport otherwise for backwards compatibility)
  • Updated SdkGeneratorCli to resolve naming and pass it through to SdkGenerator
  • Updated all declaration referencers to use namingOverride ?? <default> pattern:
    • SdkRootClientClassDeclarationReferencer (client name)
    • GenericAPISdkErrorDeclarationReferencer (error name)
    • TimeoutSdkErrorDeclarationReferencer (timeout error name)
    • EnvironmentsDeclarationReferencer (environment + environment URLs names)
    • VersionDeclarationReferencer (version name)
  • Updated DynamicSnippetsGeneratorContext to use resolved client and environment names
  • Added seed test fixture simple-api/naming with unique, non-inferable names to verify each override is applied independently
  • Added seed test fixture simple-api/naming-shorthand using string shorthand naming: acme to verify PascalCase default derivation
  • Added v3.56.0 changelog entry

Review Checklist

  • ResolvedNaming interface is duplicated in SdkGenerator.ts and getNamespaceExport.tsSdkGenerator package lacks a dependency on @fern-api/typescript-browser-compatible-base, so importing would require adding a new dep for a 7-field interface. Duplication is intentional.
  • namingOverride is passed to SdkClientClassDeclarationReferencer which forwards it to both root and subpackage referencers — verified subpackage client correctly ignores it (derives from subpackage.name.pascalCase.unsafeName, not root naming).
  • An empty naming: {} object (no fields set) triggers PascalCase derivation because naming != null is true — confirmed acceptable behavior.
  • Added naming-shorthand fixture exercising the default derivation path (naming: acme without explicit overrides).
  • naming.namespace and string shorthand are validated as valid JS identifiers via Zod .refine() (rejects my-api, etc.).

Items for human reviewer attention

  • The jsIdentifier Zod .refine() changes the inferred type — verify downstream consumers handle this correctly (string fields that pass through the refinement).
  • The string shorthand naming: "acme" normalizes to {} in resolveNaming, which triggers PascalCase derivation via naming != null. Confirm this is the desired behavior for all edge cases.

Testing

  • Lint checks pass (pnpm run check)
  • Seed test fixtures added and generated output committed (simple-api/naming + simple-api/naming-shorthand)
  • All 19 simple-api seed tests pass locally (including both new fixtures)
  • Existing tests unaffected (backwards compatible — all naming overrides are optional)

Open with Devin

…trol of class/type names

Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@claude
Copy link

claude bot commented Mar 13, 2026

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit in Settings → Usage.

Once credits are available, reopen this pull request to trigger a review.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration bot and others added 3 commits March 13, 2026 22:52
…ng casing

Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
…explicitly provided

Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
Comment on lines +447 to +453
namespace: xai
client: XAiClient
error: XAiError
timeoutError: XAiTimeoutError
environment: XAiEnvironment
environmentUrls: XAiEnvironmentUrls
version: XAiVersion
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you actually give unique names for each so we can verify none of them are accidentally inferred. Also don't use xai, our prospect, directly in the code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the fixture to use unique, non-inferable names so we can verify none are accidentally derived:

naming:
  namespace: acme
  client: AcmeSdkClient
  error: AcmeApiError
  timeoutError: AcmeRequestTimeoutError
  environment: AcmeApiEnvironment
  environmentUrls: AcmeApiEnvironmentUrls
  version: AcmeApiVersion

Each name is distinct and wouldn't match what PascalCase derivation would produce (e.g., AcmeSdkClient vs default AcmeClient, AcmeApiError vs default AcmeError, AcmeRequestTimeoutError vs default AcmeTimeoutError).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now, allow naming: acme, and derive everything from the shorthand.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! String shorthand naming: acme is now supported and derives all names via PascalCase:

naming: acme

Produces: AcmeClient, AcmeError, AcmeTimeoutError, AcmeEnvironment, AcmeEnvironmentUrls, AcmeVersion with namespace export acme.

Also added:

  • A naming-shorthand seed fixture exercising the default derivation path
  • JS identifier validation on naming.namespace and the string shorthand (rejects invalid identifiers like my-api)
  • Updated docs to document the string shorthand form

devin-ai-integration bot and others added 3 commits March 14, 2026 00:19
Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
…d fixture

Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
@fern-support fern-support merged commit 98c1a0c into main Mar 14, 2026
97 checks passed
@fern-support fern-support deleted the devin/1773441614-add-naming-config branch March 14, 2026 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants