feat(typescript): add naming configuration object for independent control of class/type names#13545
Conversation
…trol of class/type names Co-Authored-By: Niels Swimberghe <3382717+Swimburger@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
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. |
…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>
seed/ts-sdk/seed.yml
Outdated
| namespace: xai | ||
| client: XAiClient | ||
| error: XAiError | ||
| timeoutError: XAiTimeoutError | ||
| environment: XAiEnvironment | ||
| environmentUrls: XAiEnvironmentUrls | ||
| version: XAiVersion |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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: AcmeApiVersionEach 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).
There was a problem hiding this comment.
now, allow naming: acme, and derive everything from the shorthand.
There was a problem hiding this comment.
Done! String shorthand naming: acme is now supported and derives all names via PascalCase:
naming: acmeProduces: AcmeClient, AcmeError, AcmeTimeoutError, AcmeEnvironment, AcmeEnvironmentUrls, AcmeVersion with namespace export acme.
Also added:
- A
naming-shorthandseed fixture exercising the default derivation path - JS identifier validation on
naming.namespaceand the string shorthand (rejects invalid identifiers likemy-api) - Updated docs to document the string shorthand form
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>
Description
Refs: Requested by @Swimburger
Link to Devin Session: https://app.devin.ai/sessions/4ba47fb86534412697f8c6063795cd0c
Adds a new
namingconfiguration 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 existingnamespaceExportconfig continues to work for backwards compatibility.Supports both a string shorthand and a full object form:
When individual overrides are not provided, they are derived from
PascalCase(namespace)+ suffix (e.g.,namespace: "acme"→AcmeClient,AcmeError, etc.). When nonamingconfig is present at all,namespaceExportis used as-is for suffix derivation, preserving backwards compatibility (e.g.,namespaceExport: "MySDK"→MySDKClient).Changes Made
NamingConfigSchematoTypescriptCustomConfigSchema.tsas az.union([string, object])with 7 optional string fieldsnaming.namespaceand the string shorthand form (rejects invalid identifiers likemy-api)NamingConfigtype (string | NamingObjectConfig) andnamingfield toSdkCustomConfiggetNamespaceExport()to acceptnaming(string or object) with priority:naming.namespace(or string value) >namespaceExport> defaultresolveNaming()utility that resolves all naming overrides with conditionally PascalCased defaults (PascalCase whennamingconfig is explicitly provided; rawnamespaceExportotherwise for backwards compatibility)SdkGeneratorClito resolve naming and pass it through toSdkGeneratornamingOverride ?? <default>pattern:SdkRootClientClassDeclarationReferencer(client name)GenericAPISdkErrorDeclarationReferencer(error name)TimeoutSdkErrorDeclarationReferencer(timeout error name)EnvironmentsDeclarationReferencer(environment + environment URLs names)VersionDeclarationReferencer(version name)DynamicSnippetsGeneratorContextto use resolved client and environment namessimple-api/namingwith unique, non-inferable names to verify each override is applied independentlysimple-api/naming-shorthandusing string shorthandnaming: acmeto verify PascalCase default derivationReview Checklist
ResolvedNaminginterface is duplicated inSdkGenerator.tsandgetNamespaceExport.ts—SdkGeneratorpackage 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.namingOverrideis passed toSdkClientClassDeclarationReferencerwhich forwards it to both root and subpackage referencers — verified subpackage client correctly ignores it (derives fromsubpackage.name.pascalCase.unsafeName, not root naming).naming: {}object (no fields set) triggers PascalCase derivation becausenaming != nullistrue— confirmed acceptable behavior.naming-shorthandfixture exercising the default derivation path (naming: acmewithout explicit overrides).naming.namespaceand string shorthand are validated as valid JS identifiers via Zod.refine()(rejectsmy-api, etc.).Items for human reviewer attention
jsIdentifierZod.refine()changes the inferred type — verify downstream consumers handle this correctly (string fields that pass through the refinement).naming: "acme"normalizes to{}inresolveNaming, which triggers PascalCase derivation vianaming != null. Confirm this is the desired behavior for all edge cases.Testing
pnpm run check)simple-api/naming+simple-api/naming-shorthand)