Skip to content

OpenAPI model

Andriy Mykulyak edited this page Mar 21, 2023 · 8 revisions

Object model for OpenAPI specification

Coding guidelines

Public API of this library is designed with the following goals in mind:

  • provide a rich set of features
  • make it easy to maintain the library
  • making it difficult to do wrong things (e.g. to corrupt internal state of models)

General

  • POJSO-s for OpenAPI spec are located in packages/openapi-model/src/VER/types.ts, where VER indicates version number of the specification
  • Model public API as TS interfaces, and put them in packages/openapi-model/src/VER/model/types.ts. Interface names should end with Model.
  • Implement public API using TS classes, located in packages/openapi-model/src/VER/model/ITEM.ts, where ITEM denotes the name of the corresponding entity, e.g. Components or Schema.
  • Use get() / set() to expose primitive attributes. Implement validation in setters.
  • Instead of collection attributes, model classes should expose a set of member functions (see the following sections)
  • Classes should use private ES fields to hold their data (remember, encapsulation is important).

Interface for a single model attribute

Sometimes a model owns an instance of another model (e.g. a Schema model owns an instance of ExternalDocumentation class). In this case, provide the following set of attributes and member functions to query and mutate the embedded model:

readonly item: Nullable<Item>; // make it readonly
setItem(args): Item; // creates a new, or replaces and existing value. Returns the new value
deleteItem(): void; // resets the value of the attribute to its default state (most often the `null`)

Interface for an indexed collection of Item models

Sometimes a model maintains an indexed collection of other models (e.g. Components maintains a collection of Schema objects). In such cases, you should provide a set of member functions:

Basic version

readonly itemCount: number;
items(): IterableIterator<Item>;
itemAt(index: number): Item;
deleteItemAt(index: number): void;
clearItems(): void;

If you need to lookup / mutate the collection based on other attribute, add corresponding functions. For example, a list of Server objects can also be queried / mutated by using URLs.

getServer(url: string): Server | undefined;
getServerOrThrow(url: string): Server;
deleteServer(url: string): void;

Interface for a set-like collection of Item models (i.e. set-like)

Basic version

readonly itemCount: number;
items(): IterableIterator<Item>;
hasItem(item: Item): boolean;
deleteItem(item: Item): void;
clearItems(): void;

Interface for a key-based collection of Item models (i.e. map-like)

Basic version

readonly itemCount: number;
itemKeys(): IterableIterator<string>;
items(): IterableIterator<[strig, Item]>;
hasItem(key: string): boolean;
getItem(key: string): Item | undefined;
getItemOrThrow(key: string): Item;
deleteItem(key: string): void;
clearItems(): void;

if you need to set models (e.g. for shared instances), add the following method

setItemModel(key: string, model: Item): void;