Open astahmer opened 1 year ago
also a "contributing" with a link to changeset could be nice
Just wanted to give one example of where the docs could be improved 😊. I have a Spring Boot with Spring Data Rest API, which auto-generates all crud endpoints based on the entities you defined in your project. It does this in a HAL format. The downside of this format is that it's very verbose.
So when I tried this library out, all my response types were z.void()
, even though the openapi spec was v3. So after just randomly trying the complexity-threshold
flag and setting it to 100, it worked 😎.
@astahmer really love the work that is done here, thanks ❤️! It really fills the void when unable to use typescript on the backend.
hey ! glad it heps ! 🙏
can you provide a minimal repro of that bug ? it seems very weird to me that it's fixed with complexity-threshold
😅
the point of that option is (or should be, apparently) to give somewhat a bit of control on which schema will be inlined or assigned to a variable with a name (and therefore re-used rather than duplicated)
@astahmer Whoops! You're totally correct, removing the flag and running it again still worked 😅.
There was one other thing that I configured on the API server. By default, by using HAL, the content type by default is application/hal+json
, not application/json
. When I set the default content type on the server to application/json
(even though it's still using HAL), the script works. Maybe that has something to do with it?
The script I used was pnpm dlx openapi-zod-client http://localhost:8080/v3/api-docs -o src/schema.ts
, so nothing strange here, I guess. Here is the spec (you can see there's only application/json
for the POST/PUT/PATCH, which is indeed the only one that works):
openapi: 3.0.1
info:
title: OpenAPI definition
version: v0
servers:
- url: http://localhost:8080
description: Generated server url
paths:
/adventures:
get:
tags:
- adventure-entity-controller
description: get-adventure
operationId: getCollectionResource-adventure-get_1
responses:
"200":
description: OK
content:
application/hal+json:
schema:
$ref: '#/components/schemas/CollectionModelEntityModelAdventure'
application/x-spring-data-compact+json:
schema:
$ref: '#/components/schemas/CollectionModelEntityModelAdventure'
text/uri-list:
schema:
type: string
post:
tags:
- adventure-entity-controller
description: create-adventure
operationId: postCollectionResource-adventure-post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AdventureRequestBody'
required: true
responses:
"201":
description: Created
content:
application/hal+json:
schema:
$ref: '#/components/schemas/EntityModelAdventure'
/adventures/search/existsByName:
get:
tags:
- adventure-search-controller
operationId: executeSearch-adventure-get
parameters:
- name: name
in: query
schema:
type: string
responses:
"200":
description: OK
content:
application/hal+json:
schema:
type: boolean
"404":
description: Not Found
/adventures/{id}:
get:
tags:
- adventure-entity-controller
description: get-adventure
operationId: getItemResource-adventure-get
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/hal+json:
schema:
$ref: '#/components/schemas/EntityModelAdventure'
"404":
description: Not Found
put:
tags:
- adventure-entity-controller
description: update-adventure
operationId: putItemResource-adventure-put
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AdventureRequestBody'
required: true
responses:
"200":
description: OK
content:
application/hal+json:
schema:
$ref: '#/components/schemas/EntityModelAdventure'
"201":
description: Created
content:
application/hal+json:
schema:
$ref: '#/components/schemas/EntityModelAdventure'
"204":
description: No Content
delete:
tags:
- adventure-entity-controller
description: delete-adventure
operationId: deleteItemResource-adventure-delete
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"204":
description: No Content
"404":
description: Not Found
patch:
tags:
- adventure-entity-controller
description: patch-adventure
operationId: patchItemResource-adventure-patch
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AdventureRequestBody'
required: true
responses:
"200":
description: OK
content:
application/hal+json:
schema:
$ref: '#/components/schemas/EntityModelAdventure'
"204":
description: No Content
/profile:
get:
tags:
- profile-controller
operationId: listAllFormsOfMetadata_1
responses:
"200":
description: OK
content:
application/hal+json:
schema:
$ref: '#/components/schemas/RepresentationModelObject'
/profile/adventures:
get:
tags:
- profile-controller
operationId: descriptor_1_1_1
responses:
"200":
description: OK
content:
'*/*':
schema:
type: string
application/alps+json:
schema:
type: string
application/schema+json:
schema:
$ref: '#/components/schemas/JsonSchema'
components:
schemas:
AbstractJsonSchemaPropertyObject:
type: object
properties:
title:
type: string
readOnly:
type: boolean
Item:
type: object
properties:
type:
type: string
properties:
type: object
additionalProperties:
$ref: '#/components/schemas/AbstractJsonSchemaPropertyObject'
requiredProperties:
type: array
items:
type: string
JsonSchema:
type: object
properties:
title:
type: string
description:
type: string
properties:
type: object
additionalProperties:
$ref: '#/components/schemas/AbstractJsonSchemaPropertyObject'
requiredProperties:
type: array
items:
type: string
definitions:
type: object
additionalProperties:
$ref: '#/components/schemas/Item'
type:
type: string
$schema:
type: string
Links:
type: object
additionalProperties:
$ref: '#/components/schemas/Link'
RepresentationModelObject:
type: object
properties:
_links:
$ref: '#/components/schemas/Links'
EntityModelAdventure:
required:
- name
- teachingDays
type: object
properties:
name:
maxLength: 255
minLength: 3
type: string
category:
maxLength: 255
minLength: 3
type: string
teachingDays:
type: array
items:
type: integer
format: int32
externalId:
type: integer
format: int32
_links:
$ref: '#/components/schemas/Links'
CollectionModelEntityModelAdventure:
type: object
properties:
_embedded:
type: object
properties:
adventures:
type: array
items:
$ref: '#/components/schemas/EntityModelAdventure'
_links:
$ref: '#/components/schemas/Links'
AdventureRequestBody:
required:
- name
- teachingDays
type: object
properties:
id:
type: integer
format: int64
name:
maxLength: 255
minLength: 3
type: string
category:
maxLength: 255
minLength: 3
type: string
teachingDays:
type: array
items:
type: integer
format: int32
externalId:
type: integer
format: int32
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
ah yes, makes sense now
this is the option you're looking for then (and this is the default value):
--media-type-expr <expr> Pass an expression to determine which response content should be allowed
when used like this pnpx openapi-zod-client ./petstore.yaml -o ./api.client.ts --media-type-expr="mediaType === 'application/hal+json'
, it works fine
you could also allow both with true
or mediaType.includes("json")
can try it here
Thanks! I tried the --media-type-expr
, though I didn't know I had to create the expression like that 😳. Sorry for hijacking this issue, and thank you again for creating this. Amazing project!
this was done very quickly when the project was at the proof of concept stage, it hasn't been updated much since and it could benefit from a bit of a presentation effort