-
Notifications
You must be signed in to change notification settings - Fork 2
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
wip: foundation for OpenApi Parser #1814
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Skipped Deployment
|
📦 Next.js Bundle Analysis for fern-platform-monorepoThis analysis was generated by the Next.js Bundle Analysis action. 🤖 This PR introduced no changes to the JavaScript bundle! 🙌 |
Playwright test resultsDetails 101 tests across 10 suites Flaky testschromium › forward-proxy/nextjs.spec.ts › capture the flag Skipped testschromium › posthog.spec.ts › Posthog loads successfully |
packages/parsers/openapi/shared/composable/availability.node.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/interfaces/api.node.interface.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/interfaces/api.node.interface.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/interfaces/api.node.interface.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/composable/availability.node.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/interfaces/fdr.stage.interface.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/composable/availability.node.ts
Outdated
Show resolved
Hide resolved
import { SchemaObject } from "../../../openapi/shared/openapi.types"; | ||
import { createMockContext } from "../../createMockContext.util"; | ||
|
||
describe("ObjectNode", () => { |
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.
mega nit: i think it might be nicer to put these test files through out the code base as opposed to the top, that way you can see object.node.ts
and object.node.test.ts
side-by-side
packages/parsers/openapi/shared/nodes/primitives/number/float.node.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/nodes/primitives/number/float.node.ts
Outdated
Show resolved
Hide resolved
packages/parsers/openapi/shared/nodes/primitives/number/integer.node.ts
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
function convertExtraPropertiesBoolean(displayName: string | undefined): { |
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.
this pattern is interesting -- it is done for extensibility. If we want to add a new type of output to a node in the future, can be as simple as adding a new member to the return type of this function. @dsinghvi
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.
cool -- it feels a little complex but happy to defer to you
) { | ||
super(input, context, accessPath, pathId); | ||
|
||
if (typeof input.default !== "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.
what if it equals null, wont this error?
| StringConverterNode.Input; | ||
|
||
export class SchemaConverterNode extends BaseOpenApiV3_1Node< | ||
OpenAPIV3_1.SchemaObject, |
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 think this probably should handle Schema | Reference
// break; | ||
// } | ||
|
||
if (input != null) { |
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.
can the input here even be null?
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.
no, this was just to satisfy the type checker in an intermediate fashion, but can be removed
maxLength: number | undefined; | ||
|
||
private mapToFdrType = ( | ||
format: ConstArrayToType<typeof OPENAPI_STRING_TYPE_FORMAT>, |
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.
what happens if format is undefined
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.
it returns "string". The property should be set to default to "string", however
return new ReferenceConverterNode(input, context, accessPath, pathId); | ||
} | ||
return new SchemaConverterNode(input, context, accessPath, pathId); | ||
} |
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: thoughts on putting this in the SchemaNode
that way regardless of whatever schema you have: a reference or an inlined shape, it will work
import { OpenAPIV3_1 } from "openapi-types"; | ||
|
||
export function mapReferenceObject(referenceObject: OpenAPIV3_1.ReferenceObject): OpenAPIV3_1.SchemaObject { | ||
return referenceObject.$ref as OpenAPIV3_1.SchemaObject; |
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.
this feels suspect, what's the utility of this coercion?
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.
oh, this is a placeholder for now -- need to migrate the resolution logic in from fern main repo, and it should live in this function. I'll leave a TODO comment
// if (input.allOf != null) { | ||
// this.extends = input.allOf | ||
// .map((type) => chooseReferenceOrSchemaNode(type, context, accessPath, pathId)) | ||
// .filter(isNonNullish); |
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.
what does chooseReferenceOrSchemaNode
do? I could see a SchemaOrReferenceConverterNode.ts
so that you can just directly pass the input in
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.
discussed offline -- this might be confusing for folks if there are two types of nodes that accept ReferenceObjects, but is also easily portable into the SchemaNode
|
||
if (this.valueShape == null) { | ||
this.context.errors.error({ | ||
message: `Unprocessable type shape: ${this.propertyKey}`, |
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.
errors should speak the language of the input to make it easier for the user to understand
import { ReferenceConverterNode } from "./ReferenceConverter.node"; | ||
import { SchemaConverterNode } from "./SchemaConverter.node"; | ||
|
||
export class ObjectPropertyConverterNode extends BaseOpenApiV3_1Node< |
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.
why do you need this entire class at all? ideally you should just be able to redirect all object properties back to the schema node (example: https://github.com/fern-api/fern/blob/5ab95904f1a1d1a0fb4a950d1f046b8d603b78c6/generators/openapi/src/converters/convertObject.ts#L30)
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.
this is a good point, this logic should live in schema node, yeah
OpenAPIV3_1.SchemaObject, | ||
FdrAPI.api.latest.TypeShape | undefined | ||
> { | ||
typeShapeNode: { convert: () => FdrAPI.api.latest.TypeShape | undefined } | undefined; |
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.
what is this?
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.
This is the same pattern as above, it encapsulates the conversion function so that it's easy to reason about how the domain object functions should convert -- if singular functions, those will be splayed into the constructor (just a way to group for different exports)
Note: Ignore any of the files in
temporary
, those are there so that boilerplate does not need to be implemented again.This PR introduces the base nodes that are necessary for parsing OpenApi Spec.
It introduces 3 abstractions:
The nodes created are:
Primitives:
String --> these correspond to any type: "string" nodes we encounter in OpenApi spec
Number --> these correspond to any type: "integer | number" nodes we encounter in OpenApi spec
Schema: An input node that helps us recognize schemas/references as we encounter them in OpenApi spec.
Reference: An input node that helps us to resolve references or pass them as Alias types.
Object (and all derivatives): An output node that helps us to parse any schema from OpenApi into the correct Fdr shapes.
Additionally, there are a few of types files introduced for cleaner organization: