-
Notifications
You must be signed in to change notification settings - Fork 427
Implement typescript client generation #9911
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements TypeScript client SDK generation for the lakeFS project using OpenAPI Generator's typescript-fetch template. The generated SDK provides type-safe client code compatible with Node.js 18+, browsers, Deno, Bun, and React Native, bringing TypeScript support in line with existing Python, Java, and Rust clients.
Key changes:
- Added TypeScript client generation configuration and build tooling
- Generated type-safe TypeScript models from OpenAPI schema
- Implemented cleanup script to resolve duplicate export issues from multi-tagged operations
Reviewed changes
Copilot reviewed 140 out of 305 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
clients/typescript/src/models/*.ts |
Auto-generated TypeScript interface definitions and JSON serialization functions for all API models |
clients/typescript/src/index.ts |
Main entry point exporting runtime, APIs, and models |
clients/typescript/.openapi-generator/VERSION |
OpenAPI Generator version tracking (7.0.1) |
clients/typescript/.npmignore |
NPM package exclusion configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| 'blockstoreType': json['blockstore_type'], | ||
| 'blockstoreNamespaceExample': json['blockstore_namespace_example'], | ||
| 'blockstoreNamespaceValidityRegex': json['blockstore_namespace_ValidityRegex'], |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent casing in JSON key name. The key 'blockstore_namespace_ValidityRegex' uses mixed camelCase and PascalCase. This should be 'blockstore_namespace_validity_regex' to match the snake_case pattern used consistently throughout other fields.
|
|
||
| 'blockstore_type': value.blockstoreType, | ||
| 'blockstore_namespace_example': value.blockstoreNamespaceExample, | ||
| 'blockstore_namespace_ValidityRegex': value.blockstoreNamespaceValidityRegex, |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent casing in JSON key name. The key 'blockstore_namespace_ValidityRegex' uses mixed camelCase and PascalCase. This should be 'blockstore_namespace_validity_regex' to match the snake_case pattern used consistently throughout other fields.
| return { | ||
|
|
||
| 'tokenExpirationDuration': !exists(json, 'token_expiration_duration') ? undefined : json['token_expiration_duration'], | ||
| 'identityRequest': json['identityRequest'], |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent JSON key casing. The key 'identityRequest' uses camelCase while all other JSON keys in the codebase use snake_case (e.g., 'token_expiration_duration'). This should be 'identity_request' for consistency.
| 'featureUpdates': json['featureUpdates'], | ||
| 'securityUpdates': json['securityUpdates'], |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent JSON key casing. The keys 'featureUpdates' and 'securityUpdates' use camelCase while all other JSON keys in the codebase use snake_case. These should be 'feature_updates' and 'security_updates' for consistency.
| 'featureUpdates': value.featureUpdates, | ||
| 'securityUpdates': value.securityUpdates, |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent JSON key casing. The keys 'featureUpdates' and 'securityUpdates' use camelCase while all other JSON keys in the codebase use snake_case. These should be 'feature_updates' and 'security_updates' for consistency.
|
Hi @zjpiazza , and welcome to the lake!
Obviously I would like to improve support for Typescript. At the same time, I hesitate to add to our maintenance burden. If the generated client is not used in the webui, would you be open to adding this client to contrib/? |
| --http-user-agent "lakefs-typescript-sdk/$(PACKAGE_VERSION)" \ | ||
| --git-user-id treeverse --git-repo-id lakeFS \ | ||
| -o /mnt/clients/typescript | ||
| @echo "Cleaning up duplicate exports from multi-tagged operations" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why we want this. All other generated clients allow access from each tag afaiu.
|
Hi @arielshaqed, yes the test stubs and other components were generated via LLM. And yes absolutely I can share the prompts used. I basically just asked it follow the existing pattern for Python and Java clients. I will review the compatibility information you linked when I have a chance. Considering that the project is already using the OpenAPI client generation, I guess I didn't see it as being a big burden to maintain the typescript client generation. I apologize if that was an oversight on my part. |
|
Thanks! Additionally, a team member points out that this PR requires us to start publishing an NPM package:
I'd like us to figure out a usage and support model for this feature. We have had very mixed results with supplying prebuilt clients: on the one hand the convenience when it works is great, but on the other hand we regularly receive requests for other forms of generated clients, even in supported languages, and for bug-fixes which can only be performed upstream, and similar. Examples include - in no particular order, and I'm sure I missed many - #8817, #8832, #8547, #7830 and #6970. I guess a use-case for this client would really help here. I am not saying we will not do this, I am saying that the required commitment is nontrivial. Would this alternative be usable?
This may give all sides what they really need in this case. |
|
Looking at the PRs you attached, I definitely see what you mean now regarding the type of requests that would arise from publishing additional clients. In terms of use case, I am building out a self service deployment portal which leverages lakeFS. Originally I was going to do this with Terraform but I have since made the switch to Pulumi, so having a TypeScript for a better developer experience made sense. I would not mind maintaining the client but I guess I'm a little confused on what the workflow would be from my side? If it isn't serving the wider community then I don't want to push the responsibility upstream 🤷 |
What would it take to publish a client(Obviously I would love for you to do this! Just covering all the steps.) Decide on a compatibility storyWe like semantic versioning (you don't have to, but this how we describe our API). The lakeFS REST API compatibility guarantees are a good start. But consider a lakeFS version bump which adds an optional parameter. This will be a minor version bump on lakeFS. The addition of that parameter will change the TypeScript API of your generated client. If that TypeScript API is no longer backwards compatible with the API of your previous version, then the generated client needs a major version bump. You might:
Decide when to updateWhen do you update the generated client? You could auto-generate for every lakeFS release, or you could generate at will. The first keeps everything up-to-date, but it might limit your options regarding compatibility of course. Publish!With all that set up, you can publish your client. What would it take to build a client only for your app?For a single project, I would probably recommend that you build the client as part of the app. So your Makefile1 would fetch the OpenAPI spec for a tag from GitHub and generate the client. The good news is that you do not need to keep your client "up to date"! The same compatibility guarantees which make auto-generating the client so much work will also mean that any 1.x client will work with any 1.y server, as long as 1.x <= 1.y OR the client uses only features available in 1.y. So in practice:
How can the lakeFS project help?
Footnotes
|
Change Description
Background
This PR adds TypeScript client SDK generation to the lakeFS project, bringing it in line with existing Python, Java, and Rust clients. TypeScript developers will now have a fully type-safe, modern SDK for interacting with the lakeFS API.
The implementation uses OpenAPI Generator's
typescript-fetchtemplate, which generates a lightweight client using the native Fetch API. This makes it compatible with Node.js 18+, browsers, Deno, Bun, and React Native.Key design decisions:
Generator choice: Selected
typescript-fetchover other TypeScript generators for its universal compatibility (browser + Node.js) and minimal runtime dependencies.Handling duplicate exports: The lakeFS OpenAPI spec includes operations with multiple tags (e.g.,
[auth, external, experimental]), which causes OpenAPI Generator to create duplicate API classes and TypeScript TS2308 errors. After researching solutions (see GitHub issues #7519 and #15637), a post-generation cleanup script was implemented that removes duplicate exports from the API index file. This is the recommended community approach and keeps the solution maintainable without modifying the OpenAPI spec.Build structure: Follows the existing pattern used by other clients (
python-static/→python/,typescript-static/→typescript/), where static configuration files are maintained separately from the generated code.New Feature
Adds TypeScript SDK generation with the following capabilities:
make client-typescripttarget integrated into existing client generation workflowvalidate-client-typescriptfor CI/CD checksFiles added:
clients/typescript-static/- Static configuration files:package.json- npm package configurationtsconfig.json- TypeScript compiler settingstypescript-codegen-config.yaml- OpenAPI Generator configuration.openapi-generator-ignore- Files to preserve during generationcleanup-exports.js- Script to remove duplicate exports from multi-tagged operationsclients/typescript/- Generated SDK (committed to git, like other clients):src/- Generated TypeScript source code.gitignore- Ignoresnode_modules/,dist/, andpackage-lock.jsonMakefile changes:
client-typescripttarget to generate and build the SDKvalidate-client-typescripttarget for git diff validationclientsandvalidate-clienttargetsGitHub Actions workflow:
.github/workflows/typescript-api-client.yamlfor automated npm publishingskip_publish_npmoption for testingNPM_TOKENsecret to be configured in repository settings before publishingTesting Details
Build verification:
Results:
dist/Validation:
The cleanup script successfully removes duplicate exports:
Breaking Change?
No breaking changes.
This PR only adds new functionality (TypeScript client generation). It does not modify: