Skip to content

Latest commit

 

History

History
146 lines (95 loc) · 6.38 KB

developer-notes.md

File metadata and controls

146 lines (95 loc) · 6.38 KB

Developer's notes

Internal schema ids

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 $ref handling

Remote/external $refs (Pet.yaml, definitions.json#/Pet) get always immediately dereferenced by fetching the specs and inlining the relevant schemas.

refHandling: import

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:

  1. Schemas get deferenced with @apidevtools/json-schema-ref-parser's dereference method which inlines relevant $ref schemas
  2. 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
  }
}
  1. 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_';
  1. Inlined and dereferenced schemas get stringified and parsed to retrieve string placeholders and their internal id value

  2. 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.

refHandling: keep

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.

Shared OpenAPI parameters

OpenAPI parameters can be $refed 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 vs JSON schema $id

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.

TypeScript cannot import json as const

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.

Handling multiple OpenApi definitions

There are currently at least 2 open points regarding handling multiple OpenApi definition files:

  • External #refs being inlined and possibly duplicated, loosing ability to reference shared components
  • Merge multiple different OpenApi definitions consistently.

External $refs 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:

Debugging tests

Comment this line out to disable schemas cleanup after tests and check the generated files.

AJV TS support

AVJ doesn't support implicit data validation and type inference, yet.

OpenApi to JSON schema conversion

OpenAPI is often described as an extension of JSON Schema, but both specs have changed over time and grown independently:

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.