Git Product home page Git Product logo

openapi-box's Issues

Generated Json() function expects argument but none provided in caller

I'm working on the OpenAI OpenAPI spec and hitting some issues with generated code. It defines a Json() function which expects an options argument, but then often doesn't seem to pass anything to it.

Consider this example with metadata in the body:

/threads/{thread_id}/messages/{message_id}:
        post:
            operationId: modifyMessage
            tags:
                - Assistants
            summary: Modifies a message.
            parameters:
                - in: path
                  name: thread_id
                  required: true
                  schema:
                      type: string
                  description: The ID of the thread to which this message belongs.
                - in: path
                  name: message_id
                  required: true
                  schema:
                      type: string
                  description: The ID of the message to modify.
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: "#/components/schemas/ModifyMessageRequest"
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: "#/components/schemas/MessageObject"
            x-oaiMeta:
                name: Modify message
                group: threads
                beta: true
                returns: The modified [message](/docs/api-reference/messages/object) object.
                examples:
                    request:
                        curl: |
                            curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123 \
                              -H "Content-Type: application/json" \
                              -H "Authorization: Bearer $OPENAI_API_KEY" \
                              -H "OpenAI-Beta: assistants=v2" \
                              -d '{
                                  "metadata": {
                                    "modified": "true",
                                    "user": "abc123"
                                  }
                                }'
                        python: |
                            from openai import OpenAI
                            client = OpenAI()

                            message = client.beta.threads.messages.update(
                              message_id="msg_abc12",
                              thread_id="thread_abc123",
                              metadata={
                                "modified": "true",
                                "user": "abc123",
                              },
                            )
                            print(message)
                        node.js: |-
                            import OpenAI from "openai";

                            const openai = new OpenAI();

                            async function main() {
                              const message = await openai.beta.threads.messages.update(
                                "thread_abc123",
                                "msg_abc123",
                                {
                                  metadata: {
                                    modified: "true",
                                    user: "abc123",
                                  },
                                }
                              }'
                    response: |
                        {
                          "id": "msg_abc123",
                          "object": "thread.message",
                          "created_at": 1699017614,
                          "assistant_id": null,
                          "thread_id": "thread_abc123",
                          "run_id": null,
                          "role": "user",
                          "content": [
                            {
                              "type": "text",
                              "text": {
                                "value": "How does AI work? Explain it in simple terms.",
                                "annotations": []
                              }
                            }
                          ],
                          "file_ids": [],
                          "metadata": {
                            "modified": "true",
                            "user": "abc123"
                          }
                        }

...

        ModifyMessageRequest:
            type: object
            additionalProperties: false
            properties:
                metadata:
                    description: *metadata_description
                    type: object
                    x-oaiTypeLabel: map
                    nullable: true

Here is what gets generated:

/**
 * @param {JsonArray | JsonRecord} [options]
 * @returns {ReturnType<typeof T.Unsafe<Json>>}
 */
const Json = (options) => T.Unsafe(T.Any(options));

// ...

cache["e72516203ab15db84c83493e3c34ce40"] = {
    metadata: T.Optional(Json()),
};

// ...

    "/threads/{thread_id}/messages/{message_id}": {
        POST: {
            args: T.Object({
                params: T.Object(cache["fbca0ddc436612e084f356472689bcb2"]),
                body: T.Object(cache["e72516203ab15db84c83493e3c34ce40"], {
                    "x-content-type": "application/json",
                    "additionalProperties": false,
                }),
            }),
            data: T.Object(cache["9919ce439b06e6cb45eba3bc75cbb9a6"], {
                "x-status-code": "200",
                "x-content-type": "application/json",
            }),
            error: T.Union([T.Any({ "x-status-code": "default" })]),
        },

In some cases, an object does get passed to Json(), but most of them are empty.

Generated schema is invalid with noImplicitAny

If typescript config enables noImpicitAny then there are multiple errors in the generated schema code.

example:

./src/schema.ts:47:15
Type error: Parameter 'options' implicitly has an 'any' type.

  45 |  * @returns {ReturnType<typeof T.Unsafe<Json>>}
  46 |  */
> 47 | const Json = (options) => T.Unsafe(T.Any(options))
     |               ^
  48 |
  49 | const cache = {}
  50 | cache['7c09545938bb5aebc0c280502225d1d9'] = {

There will also be an error on the generated cache type.

[Question] Providing an example

Hi. Could you please provide a basic implementation of import { createClient } from './src/client.js' that you used in your readme along with an example of using it with the endpoint /pet/{petId} for reference?

Unable to parse OpenAI schema

I'm trying to create TypeBox types from the OpenAI OpenAPI schema, but it's failing without much info:

yq eval -o=json resources/openapi.yaml > output/openai.json	
openapi-box output/openai.json -o openai.js
โœ– ',' expected. (412:26)
  410 |   response_format: T.Optional(T.Union(cache['69fde07c72b934b7c91a2c1808b4bc59'],{"default":"json"})),
  411 |   temperature: T.Optional(T.Number({"default":0})),
> 412 |   timestamp_granularities[]: T.Optional(T.Array(cache['1272a49c80b3dc8bc038af92e19f1d72'],{"default":["segment"]})),
      |                          ^
  413 | }
  414 | cache['ce56d7a02eda5fc5e1e6ae8f44b7df4d'] = {
  415 |   file: T.String({"format":"binary"}),

Is this an issue in the schema, generated code, or openapi-box?

Question about project architecture

I was in the process of implementing a similar tool for OpenAPI to Typebox conversion and runtime checks through Typebox validation. Then I came across this project, whose codebase seems understandable and well-written.

I wonder: is there any particular reason why you chose to implement the JSON Schema to Typebox conversion yourself instead of using https://github.com/xddq/schema2typebox?

Thank you for your effort!

Exporting named sub-schemas, not just paths?

Hi there! I gave this library a try on one of our schemas and it seems to be working as described. :)

But in order to replace our current manually written validators we'd also need individual schemas defined in components.schemas for typing implementation details, not just the api endpoints defined in paths. Example of what this part of our spec looks like:

components:
  schemas:
    Cat: 
      properties:
        name:
          type: string
    Dog: 
      properties:
        name:
          type: string

Looks like currently all the types for these schemas are being generated, but hidden inside an internal cache, and identified using hashes instead of names. Curious if you think it'd be straightforward to turn those into an exported object with their actual names as keys instead? E.g. for the above ideally it'd look something like this:

export const components = {
  schemas: {
    Cat: T.Object({
      name: T.String()
    }),
    Dog: T.Object({
      name: T.String()
    })
  },
}

nullable ignored in OpenAPI 3.0.3 spec

I'm having an issue with @geut/openapi-box v5.0.5 (and @sinclair/typebox v0.33.7). Nullable values with OpenAPI schema version 3.0.3 seem to be ignored in the generated types.

openapi: 3.0.3
info:
  description: Title
  version: 1.0.0
servers:
  - url: "https"

components:
  schemas:
    Test:
      type: object
      properties:
        testVal:
          type: string
          description: Should be a 2 character string, null or undefined
          minLength: 2
          maxLength: 2
          nullable: true

results in

Test: T.Object({
  testVal: T.Optional(T.String({ minLength: 2, maxLength: 2 })),
})

which does not allow null.

However when using OpenAPI 3.1.0 with

openapi: 3.1.0
info:
  description: Title
  version: 1.0.0
servers:
  - url: "https"

components:
  schemas:
    TestObject:
      type: object
      properties:
        testValue:
          oneOf:
            - type: string
              description: Should be a 2 character string, null or undefined
              minLength: 2
              maxLength: 2
            - type: "null"

the result is

TestObject: T.Object({
  testValue: T.Optional(
    T.Union([T.String({ minLength: 2, maxLength: 2 }), T.Null()]),
  ),
 })

which works as expected, allowing null values.

Would it be possible to handle nullable in OpenAPI 3.0.3 like this, generating a null union for nullable fields?

Consider better type for generated cache variable

This may not be something you want to address, but I'm trying to use the generated file in TypeScript. That mostly works, but one thing that breaks is:

const cache = {};

TypeScript is unhappy with this due to the keys:

Element implicitly has an 'any' type because expression of type '"80a44415499f66d2e4772a7be3d417a1"' can't be used to index type '{}'.
Property '80a44415499f66d2e4772a7be3d417a1' does not exist on type '{}'

In my code I'm switching it to this, which side-steps it:

const cache: { [key: string]: any } = {};

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.