OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.83k stars 6.58k forks source link

[BUG] [typescript-fetch] Type for map>array>item generated but not imported #6192

Open bard opened 4 years ago

bard commented 4 years ago

Bug Report Checklist

Description

When an item of an array of a map is specified through a referenced schema, the type for the item is not generated.

For example, for an endpoint specification of:

  "/characters":
    get:
      responses:
        "200":
          content:
            application/json:
              schema:
                additionalProperties:
                  type: array
                  items:
                    $ref: "#/components/schemas/Character"

And a schema specification of:

    Character:
      required: ["first", "name"]
      properties:
        id:
          type: integer
        name:
          type: string

The Character type is not generated:

api/apis/DefaultApi.ts:25:82 - error TS2304: Cannot find name 'Character'.

25     async charactersGetRaw(): Promise<runtime.ApiResponse<{ [key: string]: Array<Character>; }>> {
                                                                                    ~~~~~~~~~

api/apis/DefaultApi.ts:42:59 - error TS2304: Cannot find name 'Character'.

42     async charactersGet(): Promise<{ [key: string]: Array<Character>; }> {
                                                             ~~~~~~~~~

Found 2 errors.
openapi-generator version

4.3.1

OpenAPI declaration file content or url

https://github.com/bard/openapi-generator-missing-type/blob/master/example.yaml

Excerpt:

  "/characters":
    get:
      responses:
        "200":
          content:
            application/json:
              schema:
                additionalProperties:
                  type: array
                  items:
                    $ref: "#/components/schemas/Character"
Command line used for generation
openapi-generator generate -g typescript-fetch --additional-properties=typescriptThreePlus=true -i example.yaml -o api
Steps to reproduce
  1. Clone https://github.com/bard/openapi-generator-missing-type
  2. Run yarn install && yarn test
Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/pull/5995 seems to solve a similar issue

auto-labeler[bot] commented 4 years ago

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

bard commented 4 years ago

After investigating further, I see that the type is generated, it's just not imported.

Expected code in DefaultApi.ts:

 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

import * as runtime from '../runtime';
import {
  Character
} from '../models'

/**
 * 
 */
export class DefaultApi extends runtime.BaseAPI {

Actual code:

 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

import * as runtime from '../runtime';

/**
 * 
 */
export class DefaultApi extends runtime.BaseAPI {
Sithira commented 4 years ago

Any update on this? 😢

badsyntax commented 4 years ago

@bard I'm curious as to why you're using additionalProperties to define the response schema. If you need array of map, shouldn't it just be:

  "/characters":
    get:
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Character"

Perhaps additionalProperties is intentional but i'm struggling to understand why...

bard commented 4 years ago

@badsyntax It's not an array of maps, it's a map of array of maps, e.g. comic title to array of characters:

{
  "Superman": [
    { "firstName": "Klark", "lastName": "Kent" },
    { "firstName": "Lois", "lastName": "Lane" }
  ],
  "Batman": [
    { "firstName": "Bruce", "lastName": "Wayne" }
  ]
}

I know, not the best layout, but it's an existing API over which I have no control.

bendem commented 4 years ago

I'm having the same problem with the typescript-angular generator (I'm guessing they share the same code). I'm trying to generate code from the spring-boot actuator which contains the following schema:

{
    "type": "object",
    "additionalProperties": {
    "type": "object",
    "additionalProperties": {
        "$ref": "#/components/schemas/Link"
    }
}
full json ```json { "openapi": "3.0.1", "info": { "title": "OpenAPI definition", "version": "v0" }, "servers": [ { "url": "http://localhost:8080/api", "description": "Generated server url" } ], "tags": [ { "name": "Actuator", "description": "Monitor and interact", "externalDocs": { "description": "Spring Boot Actuator Web API Documentation", "url": "https://docs.spring.io/spring-boot/docs/current/actuator-api/html/" } } ], "paths": { "/actuator/info": { "get": { "tags": [ "Actuator" ], "summary": "Actuator web endpoint 'info'", "operationId": "handle_0", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "type": "object" } } } } } } }, "/actuator": { "get": { "tags": [ "Actuator" ], "summary": "Actuator root web endpoint", "operationId": "links_1", "responses": { "200": { "description": "OK", "content": { "*/*": { "schema": { "type": "object", "additionalProperties": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/Link" } } } } } } } } } }, "components": { "schemas": { "Link": { "type": "object", "properties": { "href": { "type": "string" }, "hreflang": { "type": "string" }, "title": { "type": "string" }, "type": { "type": "string" }, "deprecation": { "type": "string" }, "profile": { "type": "string" }, "name": { "type": "string" }, "templated": { "type": "boolean" } } } } } } ```

Same problem, the type under additionalProperties is not imported causing a compile error for the generated code:

ERROR in ./src/app/_generated/index.ts
Module build failed (from ./node_modules/@ngtools/webpack/src/index.js):
Error: ENOENT: no such file or directory, open '/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/src/app/_generated/index.ts'
    at Object.openSync (fs.js:462:3)
    at Object.readFileSync (fs.js:364:35)
    at Storage.provideSync (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:109:13)
    at CachedInputFileSystem.readFileSync (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:289:32)
    at Observable._subscribe (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/webpack-input-host.js:35:51)
    at Observable._trySubscribe (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/node_modules/rxjs/internal/Observable.js:44:25)
    at Observable.subscribe (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/node_modules/rxjs/internal/Observable.js:30:22)
    at SyncDelegateHost._doSyncCall (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@angular-devkit/core/src/virtual-fs/host/sync.js:22:20)
    at SyncDelegateHost.read (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@angular-devkit/core/src/virtual-fs/host/sync.js:49:21)
    at WebpackCompilerHost.readFile (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/compiler_host.js:150:42)
    at WebpackCompilerHost.getSourceFile (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/compiler_host.js:261:34)
    at AngularCompilerPlugin.getDependencies (/mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/angular_compiler_plugin.js:942:47)
    at /mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/loader.js:63:59
    at Array.forEach (<anonymous>)
    at /mnt/c/Users/demarteaub/Projects/clarified-arbustum/client/node_modules/@ngtools/webpack/src/loader.js:63:18
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
bendem commented 4 years ago

For reference, I work around this by fixing the generated file on the fly, it is very brittle but the only way to not break our CI build.

rm -rf src/app/_generated/ \
  && openapi-generator batch openapi-config/localhost.yml \
  && sed -i "1s|^|import { Link } from '../model/models';\n|" src/app/_generated/api/actuator.service.ts