Each processed schemas is assigned with a unique internal id holding schema name and path information /<path>/<name>
.
Eg: /components/schemas/SchemaName
.
Internal ids are used to refer to any specific schemas and retrieve schema path and name.
Remote/external $ref
s (Pet.yaml
, definitions.json#/Pet
) get always immediately dereferenced by fetching the specs and inlining the relevant schemas.
import refHandling
option introduces the ability NOT to inline $ref
schemas, but to generate the relevant import statements and reference them as external schema files.
At the time of writing the implementation is build around @apidevtools/json-schema-ref-parser
's dereference
method options and works as follows:
- Schemas get deferenced with
@apidevtools/json-schema-ref-parser
'sdereference
method which inlines relevant$ref
schemas - Inlined schemas get marked with a symbol property holding the internal schema id (
/components/schemas/Bar
)
{
bar: {
[Symbol('id')]: '/components/schemas/Bar',
// ...Inlined schema props
}
}
- Inlined and dereferenced schemas get traversed and all schemas marked with
Symbol('id')
prop get replaced with a string placeholder holding the original internal schema id. Note that string placeholders can be safely stringified.
{
bar: '_OTJS-START_/components/schemas/Bar_OTJS-END_';
}
Note: alias definitions (eg. Foo: "#components/schemas/Bar"
) will result in a plain string placeholder.
'_OTJS-START_/components/schemas/Bar_OTJS-END_';
-
Inlined and dereferenced schemas get stringified and parsed to retrieve string placeholders and their internal id value
-
For each string placeholder found, an import statement to the relevant
$ref
schema is prepended and the placeholder replaced with the imported schema name. 2 schemas are exported: with and without$id
.
import { without$id as componentsSchemasBar } from './Bar';
const schema = {
$id: '/components/schemas/Foo',
bar: componentsSchemasBar,
} as const;
export default schema;
const { $id, ...without$id } = schema;
export { without$id };
Schemas without $id are the ones used to resolve refs.
keep
option was implemented as last, and it currently follows the same flow as the import
except for point 5, where schemas with string placeholders are replaced with the an actual $ref
value.
OpenAPI parameters can be $ref
ed in 2 ways:
parameters:
# Locally defined parameters with $ref schema
- schema:
$ref: '#/components/schemas/Answer'
in: header
name: header-param-2
required: true
description: header-param-2 description
# Full $ref parameters
- $ref: '#/components/parameters/componentParameter'
Locally defined parameter with $ref schema should be fully supported.
Full $ref parameters are currently always inlined since parameters conversion is currently delegated to openapi-jsonschema-parameters
.
- OpenAPI
$ref
s documentation - JSON schema
$ref
s documentation - JSON schema Compound Schema Document
$id
documentation
Schemas are internally assigned to a private id with the following structure: /components/schemas/MySchema
.
$ref
values are currently assigned with the same value associated to the relevant schema $id
.
We are currently forced to generate .ts
files with as const
assertions since TypeScript cannot import JSON or any other file as const.
In this GitHub thread, TypeScript maintainers discuss the topic in depth.
There are currently at least 2 open points regarding handling multiple OpenApi definition files:
- External
#ref
s being inlined and possibly duplicated, loosing ability to reference shared components - Merge multiple different OpenApi definitions consistently.
External $ref
s are currently inlined with @apidevtools/json-schema-ref-parser
's bundle
method. We should investigate whether any OpenApi-specific library could provide a more flexible alternative:
- openapi-merger
- swagger-merger
- swagger-combine
- openapi-merge
- api-ref-resolver
- @iouring-engineering/openapi-merge
- @stoplight/json-ref-resolver
Comment this line out to disable schemas cleanup after tests and check the generated files.
AVJ doesn't support implicit data validation and type inference, yet.
OpenAPI is often described as an extension of JSON Schema, but both specs have changed over time and grown independently:
- https://medium.com/apis-you-wont-hate/openapi-and-json-schema-divergence-part-1-1daf6678d86e
- https://medium.com/apis-you-wont-hate/openapi-and-json-schema-divergence-part-2-52e282e06a05
The current conversion consists of iterating the whole OpenApi schema and converting any found property with @openapi-contrib/openapi-schema-to-json-schema
. This approach is definitely suboptimal since not all the OpenApi fields are supposed to be convertible to JSON schema.
Another approach could consist of executing the conversion only on those fields which OpenApi documentation defines as data types convertible to JSON schema.
From v3.1.0, OpenApi definitions should be valid JSON schemas, therefore no conversion should ve needed.