-
-
Notifications
You must be signed in to change notification settings - Fork 528
feat: export schemas types at root level #1260
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
Conversation
|
So this is a different approach to what I was expecting. I’m definitely against generating PascalCase INSTEAD of the core schema. But I like your idea of generating PascalCase types IN ADDITION to keeping the core schema intact. To be honest, no one’s suggested this before, but I like it! However, this does need a few things before we ship it:
Again, still in favor of this approach overall! But it’s worth pointing out the original version of the library took the same approach but had to move away from this because it was unworkable for most schemas. The scoped namespacing handles conflict resolution, and generates all paths by its design—it mirrors schema authorship. So releasing a flag that promises friendly names does have to solve these hard problems, unfortunately. Otherwise we’ll just get a bunch of bug reports to fix them later, and it may be harder to do after it’s been integrated without rewriting it. |
@@ -253,7 +256,7 @@ async function openapiTS(schema: string | URL | OpenAPI3 | Readable, options: Op | |||
output.splice(1, 0, "/** WithRequired type helpers */", "type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };", ""); | |||
} | |||
|
|||
return output.join("\n"); | |||
return output.join("\n").concat(schemasExportedTypes); |
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.
nit:
return output.join("\n").concat(schemasExportedTypes); | |
// --root-types | |
if (options.rootTypes) { | |
const schemasExportedTypes = transformComponentsObjectToTypes((allSchemas["."].schema as OpenAPI3).components; | |
output.push(schemasExportedTypes); | |
} | |
return output.join("\n"); |
This has the same execution as what you wrote, but it contains all the logic in one place rather than scattering it around in multiple places (IMO it’s weird for one option and one option alone to claim the last few lines of the final output; this change would make reordering at any point easier)
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.
I wish I could do this, but allSchemas
is deleted line 112 of this file 😅
I imagine you did this on purpose, is there any counter-indication to remove this line ?
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.
Sorry; not sure I understand?
@@ -639,6 +639,8 @@ export interface OpenAPITSOptions { | |||
httpMethod?: string; | |||
/** (optional) Export type instead of interface */ | |||
exportType?: boolean; | |||
/** (optional) Generate schemas types at root level */ | |||
rootTypes?: boolean; |
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.
let’s also add this to the ctx object so it’s more explicitly passed around
Thanks 😁
For sure ! Before spending more times on it I wanted to ensure that I wasn't going against the philosophy of the project :)
Didn't knew about it, I'm not working a lot with OpenAPI, mostly consuming it.
👍 Agree would be more performant :)
Don't have any arg, since my initial need was fulfilled with the root schemas, I didn't dive deeper. Thanks for feedback I'll work on it 😄 |
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.
Still in favor of this merging! But just marking as “changes requested” until it’s ready for review again.
No problem 👍 |
fe133e5
to
4d0866e
Compare
e1a91c6
to
283dcda
Compare
b69f7fc
to
94c9b8f
Compare
@jean-smaug @drwpow Is there any way to test it locally? If I run it like this I can figure out from where 6.5.3 it is coming from. Here's how I call it: |
@alex-aveva it’s because the original PR was based off of I’m not sure of the status of this PR; some tests were added but we still need a few more tests (such as testing conflicts are handled, testing generating rootTypes from external sources, and testing that shapes beyond I did rebase it against the |
@@ -6,6 +6,12 @@ | |||
"name": "Drew Powers", | |||
"email": "[email protected]" | |||
}, | |||
"contributors": [ |
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.
We’re not using this field in package.json
. We’re tracking contributors via the docs site. Let’s remove it.
@jean-smaug @drwpow I was able to test this today.
git clone https://github.com/jean-smaug/openapi-typescript.git
curl -fsSL https://get.pnpm.io/install.sh | sh -
npm run build:openapi-typescript
After that I was able trun
✨ openapi-typescript 6.7.0
file:///home/<username>/.npm/_npx/21d31b7563e6adbc/node_modules/openapi-typescript/dist/index.js:95
for (const schema of Object.keys(typedComponents.schemas)) {
^
TypeError: Cannot convert undefined or null to object
at Function.keys (<anonymous>)
at openapiTS (file:///home/<username>/.npm/_npx/21d31b7563e6adbc/node_modules/openapi-typescript/dist/index.js:95:37)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async generateSchema (file:///home/<username>/.npm/_npx/21d31b7563e6adbc/node_modules/openapi-typescript/bin/cli.js:83:18)
at async file:///home/<username>/.npm/_npx/21d31b7563e6adbc/node_modules/openapi-typescript/bin/cli.js:192:7
at async Promise.all (index 0)
at async main (file:///home/<username>/.npm/_npx/21d31b7563e6adbc/node_modules/openapi-typescript/bin/cli.js:183:3)
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/
export type AccessControlList = external['.']['components']['schemas']['AccessControlList'];
export type AccessControlEntry = external['.']['components']['schemas']['AccessControlEntry'];
export type Trustee = external['.']['components']['schemas']['Trustee'];
export type TrusteeType = external['.']['components']['schemas']['TrusteeType']; Not exactly sure how these types can be used. |
Just checking in on this—again, still in favor of merging, but we still need:
Unfortunately, these are all requirements for merging, because this is a big feature. And big features place a burden on maintainers to carry longterm. This still has lots of sharp edges that need to be filed down to last in the project. |
@jean-smaug I'm happy to help with writing unit tests or anything really, just let me know. |
@drwpow @jean-smaug If there are no objections, I would love to finish this PR. I have some spare time to work on it. Please let me know! |
@alex-aveva I’m not sure about the state of this; at this point I think it’s fair to take over (and open a new PR)! The list of requirements still has to be met though 😅 |
@drwpow I'll review the current state and aim to finalize it, thank you for the confirmation! |
If this PR is being picked up again, I'd like to chime in with my 2 cents on this part of the requested changes:
Although aliasing like this would be more performant and arguably safe, from my point of view there are a couple of substantial downsides as well. First off, aliasing does not retain docstrings, so any generated descriptions are lost. In my eyes, semantic descriptions are key enablers for ease-of-use, and with the current setup it is necessary to copy schema descriptions from generated file into the file which re-exposes types if you want to retain this information. Secondly, it renders tools such as TypeDoc less valuable for documenting types, since the shape is not inferred from aliases. The initial screenshot posted in the PR description shows output which is exactly what I want to achieve, and some benefits would be lost by the quoted suggestion. @drwpow do these arguments make sense to you? @alex-aveva if this PR ends up taking the approach of rebuilding types to give full access to the shape and docstrings directly, I'd be happy to contribute in finalising the PR -- don't hesitate to reach out :) |
@alex-aveva did you find time to pick this up? Would be a banger feature. |
|
Ah that’s a great callout. If it’s feasible, I’d like to still alias it but copy the docstring from the aliased type for this very reason. In 6.x this is difficult because there’s no resolver, but 7.x’s resolver makes lookups trivial and fast. So if this lands in 6.x, it could get this fix when being ported into 7.x. |
need any help with this? its an absolute must have for a large codebase I have things like: const orgs = ref<components['schemas']['WebApiEndpointsOrganisationModelsOrganisationWebResponse']['organisations']>() |
@cmcnicholas the current status of this is there is a lot of work to do, but if someone else wants to pick it up it’s fair game (so long as they hit the original list of requirements and take into account other great feedback here like @knut-sverdrup-adsk, @alex-aveva, and others)! I’m going to close this PR not as a “won’t accept this in the repo” but just leaving room for someone else to pick it up. Just to restate my feelings, this isn’t something that’s high on my priority list, but since there seems to be community interest in it I’d accept the addition from the community. But as this PR stands it would leave me a lot of work in bugfixes and maintenance getting this to meet the existing quality of the rest of the codebase, hence my change request. If anyone else makes a PR that adds this feature and doesn’t leave any loose ends untied, I’d happily accept it and ship it. |
Changes
Parse the schemas node in order to exports them as types at root level of the file.
How to Review
You can run examples with the
--root-types
flag 😄It will add the following exports at root level (example with Stripe)
Checklist
docs/
updated (if necessary)pnpm run update:examples
run (only applicable for openapi-typescript)