Giter VIP home page Giter VIP logo

mnahkies / openapi-code-generator Goto Github PK

View Code? Open in Web Editor NEW
12.0 6.0 1.0 12.03 MB

A code generation tool for openapi 3 / 3.1 specifications written in typescript, primarily aimed at generating typescript clients and server stubs. Other target languages may be added in future.

Home Page: https://openapi-code-generator.nahkies.co.nz/

License: MIT License

JavaScript 6.43% TypeScript 93.39% Shell 0.03% HTML 0.15% CSS 0.01%
openapi openapi-generator typescript openapi3 devtools openapi31 zod angular axios koa

openapi-code-generator's Introduction

@nahkies/openapi-code-generator

CI/CD npm

This project should be considered alpha quality. However, as shown by the integration tests, it does a fair job of generating a strongly typed client for large/complex definitions like the GitHub api.

Project Structure

The repository is structured as a mono repo of several npm packages that work together under ./packages:

The openapi-code-generator package is the main package, whilst the others are supporting packages used at runtime by the code output by some of the templates.

Integration test definitions live in ./integration-tests-definitions and the generated code output to ./integration-tests

Scripts to refresh the test data live in ./scripts

Documentation

Please see ./packages/openapi-code-generator for the main README.md, detailing the goals of the project and usage information.

Contributing

Contributing guidelines can be found in ./CONTRIBUTING.md.

An overview of the codebase architecture is in ./packages/openapi-code-generator/ARCHITECTURE.md

License

See ./LICENSE

openapi-code-generator's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

asfaltboy

openapi-code-generator's Issues

Add config flag to change schema parser

Support is implemented for both joi and zod to parse schema's. Currently the choice of which to use is hard coded, add a cli flag to choose between the different implementations

Refactor static code snippets to be normal files

Currently static code snippets for helper functions are stored as inline template strings.

They would be easier to work with as normal typescript files, and then we could write unit tests directly against them rather than indirectly testing the generated output.

OpenAPI 3.1.x schemas falsely fail validation with ajv

Expected Behavior
A valid openapi: "3.1.0" document should pass initial validation against the openapi 3.1 specification without errors.

Actual Behavior
Validation fails with confusing / obtuse error messages.

Cause
It seems that ajv does not support some of the keywords used in defining the specification properly, causing it to fail:

The best thing to do is probably wait for ajv to improve support for $dynamicAnchor, and skip validation for 3.1 specifications in the meantime.

improve additionalProperties support

Currently we always type additionalProperties as Record<string, unknown> but it's possible for a more specific type to be used in some cases.

additionalProperties - Value can be boolean or object. Inline or referenced schema MUST be of a Schema Object and not a standard JSON Schema. Consistent with JSON Schema, additionalProperties defaults to true.

ref: https://spec.openapis.org/oas/v3.0.3#properties

// TODO better support
const additionalProperties =
schemaObject.additionalProperties || properties.length === 0
? "[key: string]: unknown"
: ""

typescript-fetch: support runtime parsing

currently only the typescript-koa does any runtime parsing/validation.

add support to the typescript-fetch template for validating parameters, and parsing responses using the configured schema builder (ie: zoa / joi)

Allow more config options for ServerConfig, or allow passing our own Koa instance.

Hi there,

I've been looking for a way to generate a typescript server from an openapi schema that wasn't express based for a while now, and I am happy I found this tool, as it supports both Koa and Zod which are two library I have been using heavily in my projects, so big thanks for making it.

Now I am working on a project where I need to specify additional options to the Koa instance, one being the host options and the ability to use a custom function for the listen callback. Both of these are pretty important requirements for my project, due to how we want our output being presented to the console. Because my project makes use of node clusters, calling the startServer function means that every web cluster instance is now outputting the line server listening: ... which is not ideal, and there is no options to prevent this.

So having the option to override the default as a field in the ServerConfig type would be a good compromise, unless of course you have a better solution in mind.

Thanks

add support for multiple request body types

It's possible to declare different request bodies for different content types.

Currently we simply use the first one that we find:

// todo support multiple request body types
for (const [requestBodyContentType, definition] of Object.entries(requestBody.content)) {
return {
requestBodyContentType,
requestBodyParameter: {
name: "requestBody",
description: requestBody.description,
in: "body",
required: requestBody.required,
schema: definition.schema,
allowEmptyValue: false,
deprecated: false,
},
}
}

At a minimum we should support:

  • multipart/form-data
  • application/octet-stream
  • text/plain

Ideally we'd additionally support XML, but that might be left for it's own issue.

Embedding spec into generated code

This should definitely be it's own issue (coming from this issue) and this shouldn't be strictly related to #81.

So I have used other projects (mainly golang related) for openapi, and I was spoiled with the option of having the spec embedded into the server via base64 encoding. I'll provide this link here, that gives a good example of how that may look.

Unlike issue #81 this is not about providing documentation, but rather exposing the openapi schema itself, which can be served by the application itself, allowing someone to generate a client from that schema for the exact version of software that is hosting it. I've personally always found this way of doing it to be fitting for almost all apps that I have written using openapi.

Now I am not sure how involved you want this process to be, I personally would be fine with having it generated and a few helper functions to decode it, cache it, and then provide a function to get the cached contents of which could be served on any endpoint I wish without any forced requirements. However maybe you want the process to be more controlled, and maybe you have some function that takes an endpoint string, and then the library handles serving it up on that endpoint, with very little effort on the developer using it.

I hope this is something that makes it into the library in some way, as I see it being very beneficial.

support typespec as an input format

https://typespec.io/ seems like a pretty cool alternative specification language to openapi

they have API's that transpile it to OpenAPI 3, so it should be pretty trivial to support it as alternative input specification.

(ref: https://typespec.io/docs/libraries/openapi3/reference/js-api/functions/getOpenAPI3)

separately, I've been experimenting in private with SQL database schema + query AST introspection to produce zod schemas for a given SQL query, and toying with the idea of incorporating that into this project as another input source (alternatively since that's reasonably out of scope of the current project, separating some of the components I want to reuse from here into packages might make more sense)

Generating implementation based on tags

Having the ability to separate routes based on tags specified in the openapi schema. This would make it easier to implement routes in classes for that specific tag.

I would assume it might end up looking something like this

export type MiscEndpoints = {
  getVersion: GetVersion,
  getSpec: GetSpec,
}

export type Implementation {
  miscRoutes: MiscEndpoints ,
  // non tagged endpoint
  getInfo: GetInfo,
}

I assume this might end up requiring a little more work as to figure out that MiscRoutes implements sub routes, so I'm not sure of what the best way to do that is for this project, but hopefully this is enough information to give you an idea of what I am trying to get at.

Generally in most cases you end up having a file full of functions that implements something like /users endpoint, and you would return a router implementing those routes, but would be nice to be able to implement these routes from a class such as in my case.

Right now it's not very easy to implement from a class, cause I generally have to make another structure and target specific routes for those specific routes such as /users, and /version and /spec are misc routes.

Would like to discuss more on this topic, if you have any ideas?

support loading files from uri

Implement support for loading definition files from URI.

Should be supported for both root/entry-point file, and also for referencing external schemas, eg:

$ref: 'https://example.com/openapi.yaml#/components/responses/ClientError'

Care needs to be taken as to relative path handling. Eg: if you reference a external file using a URL, and it references a file relatively then this should be resolved relative to the URL.

See https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03 for exact specifications.

Investigate supporting async api

Async API is a specification for describing event driven architecture, that aims to keep near compatibility with openapi specifications:

Part of this content has been taken from the great work done by the folks at the OpenAPI Initiative. Mainly because it's a great work and we want to keep as much compatibility as possible with the OpenAPI Specification.

It would be good to investigate adding support for this, possible templates could include:

  • GCP PubSub
  • AWS SNS/SQS
  • Azure Service Bus
  • RabbitMQ
  • Kafka
  • ZeroMQ

https://www.asyncapi.com/docs/tutorials/getting-started/coming-from-openapi

I found a few possible errors, one which is breaking for me

So I ignored a few of the issues since, this project is still early, and they were only type issues that I could work around, but with version 0.3.0 another issue has cropped up that breaks things for me.

So the major issue that breaks things for me now, is the fact then after updating to 0.3.0 I am presented with

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './errors' is not defined by "exports" in /workspace/node_modules/@nahkies/typescript-koa-runtime/package.json

and the small but workaround issues that I have found since day one of using this, is also related in a way to the above, but not caused by it.

Cannot find module '@nahkies/typescript-koa-runtime/server' or its corresponding type declarations.ts(2307)
Cannot find module '@nahkies/typescript-koa-runtime/zod' or its corresponding type declarations.ts(2307)

it seems the runtime has no issues with these paths, but typescript does, and adding /src/ after @nahkies/typescript-koa-runtime path fixes the typescript issues, so it's just a simple path rewrite that needs to happen for the typescript types.

One last possible issue that I think you overlooked was you are linking joi definitions for zod.

It's possible one or more of these issues are related to my setup, so do let me know, thanks.

typescript-koa: response validation

Implement response validation based on status code and matching schema.

  • exact status codes take priority, followed by 2xx style ones and finally the default schema
  • include configuration flag to enable/disable at runtime
  • support both zod and joi

typescript-koa: support serving docs using redoc

add support for optionally serving documentation generated using https://github.com/Redocly/redoc for servers using typescript-koa template

essentially this will involve:

  • exposing a route /docs returning an html document including the redoc html below
  • exposing a route /openapi.yaml returning the specification used to generate the server

the html will look similar to:

<html>
<body>
    <redoc spec-url="http://petstore.swagger.io/v2/swagger.json"></redoc>
    <script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
</body>
</html>

with the spec path updated, and a sub resource integrity hash added (https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)

this functionality should be optional, and the routes configurable to ensure that it can be used without collision with the actual API surface.

What's the best way to handle authentication currently?

So far I am passing in a generic auth middleware to validate cookies/tokens for my application and then setting the state to that of a user entity. Which so far is nothing crazy and pretty standard, but when it comes to dealing with it in the routes, I seem to be writing the same code over and over again and even if abstracted into a function I still have to remember to call that function at the top of each route call.

Should I wait for per route middleware or for security schemes to be supported or is there a better way of doing this? Ideally I would make use of the libraries security schemas to implement my logic and then have that implementation called on all the routes linked with the securitySchemas specified in the openapi file, but of course I am not yet able to do that.

Any ideas?

Issue I am having with 'additionalProperties' and TypeSpec

Hi there,

So I recently found out about https://typespec.io/ and was interested in giving it ago, and so far has been pretty interesting as well as a nice difference to writing it in yaml.

However I just found my first problem since using it, and that is that they don't allow you a way to generate additionalProperties with a yes meaning I am currently unable to use my APIError object as I previously was, and that is due to the EmptyObject that is applied, which essentially forces me to do as any every time I wish to output any metadata.

export type t_APIError = {
  error: string
  message?: string
  metadata?: {
    [key: string]: EmptyObject
  }
  suggested?: string
}

Is there a way to nicely work around this or will I need to wait for some update/change for it? For now I will just override the type checking with as any until a better solution is found.

Koa parameter names don't match zod/openapi schema and causes validation errors

So for example this is what I have in my openapi schema

  /v1/users/{user_id}:
    get:
      operationId: UserGetById
      description: Get a user by ID.
      tags: [users]
      parameters:
        - name: user_id
          required: true
          in: path
          schema: { $ref: '#/components/schemas/Identifier' }
      responses:
        default: { $ref: '#/components/responses/InternalServerError' }
        '404': { $ref: '#/components/responses/NotFound' }
        '401': { $ref: '#/components/responses/Unauthorised' }
        '200': { $ref: '#/components/responses/UserGetByIdOK' }

as you can see I have the parameter as user_id and the generated schema for this becomes

const userGetByIdParamSchema = z.object({ user_id: s_Identifier })

so far this all looks fine, until you look at the route that is generated

router.get("userGetById", "/v1/users/:userId", async (ctx, next) => { ... }

and now you'll notice it's checking against userId and not user_id which leads to a validation error. I'm aware I could just rename the parameter in my openapi file to match the koa parameter, but it's probably a good idea to address this, so it's not an annoying requirement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.