Skip to content

Commit

Permalink
fix: Typescript tsc error using OpenApi.UpdatedSchema
Browse files Browse the repository at this point in the history
Replacing return type for `generateAttributeSchema()` with
OpenApi.UpdatedSchema causes tsc error, probably due to elements like
`allOf`.

Proposal is refactor UpdatedSchema more fully based on OpenAPI 3.

Also refactor old and unused schema field `common_name`.
  • Loading branch information
danielsharvey authored and theoomoregbee committed Jun 4, 2020
1 parent 58f80c9 commit 6f9a5fd
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 49 deletions.
36 changes: 17 additions & 19 deletions lib/generators.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SwaggerSailsModel, NameKeyMap, SwaggerRouteInfo, BlueprintActionTemplates, Defaults, MiddlewareType, SwaggerSailsController, Action2Response } from './interfaces';
import { Schema, Reference, Tag } from 'swagger-schema-official';
import { Reference, Tag } from 'swagger-schema-official';
import get from 'lodash/get';
import { swaggerTypes, sailAttributePropertiesMap, validationsMap, actions2Responses } from './type-formatter';
import assign from 'lodash/assign';
Expand Down Expand Up @@ -43,14 +43,14 @@ export const generateSwaggerPath = (path: string): { variables: string[]; path:
* @param {Record<string, any>} attribute Sails model attribute specification as per `Model.js` file
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const generateAttributeSchema = (attribute: NameKeyMap<any>): Schema & { oneOf?: Schema[] } => {
export const generateAttributeSchema = (attribute: NameKeyMap<any>): OpenApi.UpdatedSchema => {
const ai = attribute || {}, sts = swaggerTypes;

const type = attribute.type || 'string';
const columnType = get(attribute, ['autoMigrations', 'columnType']);
const autoIncrement = get(attribute, ['autoMigrations', 'autoIncrement']);

let schema: Schema & { oneOf?: Schema[]; common_name?: string } = {};
let schema: OpenApi.UpdatedSchema = {};

if (ai.model) {
assign(schema, {
Expand Down Expand Up @@ -152,23 +152,21 @@ export const generateAttributeSchema = (attribute: NameKeyMap<any>): Schema & {

// note: required --> required[] (not here, needs to be done at model level)

delete schema.common_name;

return schema;
}


/**
* Generate Swagger schema content describing specified Sails models.
* @see https://swagger.io/docs/specification/data-models/
* @param models parsed Sails models as per `parsers.parseModels()`
* @returns
* @param models parsed Sails models as per `parsers.parseModels()`
* @returns
*/
export const generateSchemas = (models: NameKeyMap<SwaggerSailsModel>): NameKeyMap<Schema | Reference> => {
export const generateSchemas = (models: NameKeyMap<SwaggerSailsModel>): NameKeyMap<OpenApi.UpdatedSchema | Reference> => {
return Object.keys(models)
.reduce((schemas, identiy) => {
const model = models[identiy]
const schema: Schema = {
const schema: OpenApi.UpdatedSchema = {
description: get(model, 'swagger.description', `Sails ORM Model **${model.globalId}**`),
required: [],
}
Expand All @@ -179,28 +177,28 @@ export const generateSchemas = (models: NameKeyMap<SwaggerSailsModel>): NameKeyM
props[attributeName] = generateAttributeSchema(attribute);
if (attribute.required) schema.required!.push(attributeName);
return props
}, {} as NameKeyMap<Schema>)
}, {} as NameKeyMap<OpenApi.UpdatedSchema>)

if (schema.required!.length <= 0) delete schema.required;

schemas[model.identity] = schema;

return schemas
}, {} as NameKeyMap<Schema | Reference>)
}, {} as NameKeyMap<OpenApi.UpdatedSchema | Reference>)
}

/**
* Generate Swagger schema content describing specified Sails routes/actions.
*
* @see https://swagger.io/docs/specification/paths-and-operations/
*
*
* TODO: break down this function into smaller methods and add tests separately
*
* @param routes
* @param templates
* @param defaultsValues
* @param action2s
* @param specification
*
* @param routes
* @param templates
* @param defaultsValues
* @param action2s
* @param specification
*/
export const generatePaths = (routes: SwaggerRouteInfo[], templates: BlueprintActionTemplates, defaultsValues: Defaults, action2s: NameKeyMap<SwaggerSailsController>, specification: Omit<OpenApi.OpenApi, 'paths'>): OpenApi.Paths => {
const paths = {};
Expand Down Expand Up @@ -547,4 +545,4 @@ export const generatePaths = (routes: SwaggerRouteInfo[], templates: BlueprintAc
}

return paths
}
}
8 changes: 4 additions & 4 deletions lib/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { OpenApi } from '../types/openapi';
import { Reference, Tag } from 'swagger-schema-official';
import { Reference, Tag, ExternalDocs } from 'swagger-schema-official';

export interface SwaggerGenerator {
includeRoute?: (route: SwaggerRouteInfo) => boolean;
Expand Down Expand Up @@ -48,7 +48,7 @@ export interface SwaggerAttribute {
export interface SwaggerSailsModel extends Omit<Sails.Model, 'attributes'> {
attributes: Record<string, Sails.AttributeValue & {
description?: string;
externalDocs?: OpenApi.ExternalDoc;
externalDocs?: ExternalDocs;
example?: string;
}>;
swagger: SwaggerAttribute;
Expand All @@ -68,7 +68,7 @@ export interface SwaggerSailsRouteControllerTarget extends Sails.RouteController
interface BluePrintActionTemplate {
summary: string;
description: string;
externalDocs: OpenApi.ExternalDoc;
externalDocs: ExternalDocs;
parameters: Array<'primaryKeyPathParameter' | Reference | OpenApi.Parameter>;
resultDescription: string;
notFoundDescription?: string;
Expand Down Expand Up @@ -145,4 +145,4 @@ export interface SwaggerRouteInfo {

export interface NameKeyMap<T> {
[name: string]: T;
}
}
24 changes: 11 additions & 13 deletions lib/type-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,23 @@ import { BlueprintActionTemplates, Modifiers, Action2Response, Defaults } from '

/**
* this is used to map our sails types with the allowed type defintions based on swagger specification
* @type {{integer: {common_name: string, type: string, format: string, comments: string}, long: {common_name: string, type: string, format: string, comments: string}, float: {common_name: string, type: string, format: string}, double: {common_name: string, type: string, format: string}, string: {common_name: string, type: string}, byte: {common_name: string, type: string, format: string, comments: string}, binary: {common_name: string, type: string, format: string, comments: string}, boolean: {common_name: string, type: string}, date: {common_name: string, type: string, format: string, comments: string}, datetime: {common_name: string, type: string, format: string, comments: string}, password: {common_name: string, type: string, format: string, comments: string}}}
*/
export const swaggerTypes = {
integer: { common_name: 'integer', type: 'integer', format: 'int32', /* comments: 'signed 32 bits' */ },
long: { common_name: 'long', type: 'integer', format: 'int64', /* comments: 'signed 64 bits' */ },
float: { common_name: 'float', type: 'number', format: 'float' },
double: { common_name: 'double', type: 'number', format: 'double' },
string: { common_name: 'string', type: 'string' },
byte: { common_name: 'byte', type: 'string', format: 'byte', /* comments: 'base64 encoded characters' */ },
binary: { common_name: 'binary', type: 'string', format: 'binary', /* comments: 'any sequence of octets' */ },
boolean: { common_name: 'boolean', type: 'boolean' },
date: { common_name: 'date', type: 'string', format: 'date', /* comments: 'As defined by full-date - RFC3339' */ },
integer: { type: 'integer', format: 'int32', /* comments: 'signed 32 bits' */ },
long: { type: 'integer', format: 'int64', /* comments: 'signed 64 bits' */ },
float: { type: 'number', format: 'float' },
double: { type: 'number', format: 'double' },
string: { type: 'string' },
byte: { type: 'string', format: 'byte', /* comments: 'base64 encoded characters' */ },
binary: { type: 'string', format: 'binary', /* comments: 'any sequence of octets' */ },
boolean: { type: 'boolean' },
date: { type: 'string', format: 'date', /* comments: 'As defined by full-date - RFC3339' */ },
datetime: {
common_name: 'dateTime',
type: 'string',
format: 'date-time',
/* comments: 'As defined by date-time - RFC3339' */
},
password: { common_name: 'password', type: 'string', format: 'password', /* comments: 'A hint to UIs to obscure input' */ }
password: { type: 'string', format: 'password', /* comments: 'A hint to UIs to obscure input' */ }
};

/**
Expand Down Expand Up @@ -272,4 +270,4 @@ export const defaults: Defaults = {
'404': { description: 'Resource not found' },
'500': { description: 'Internal server error' }
}
};
};
62 changes: 49 additions & 13 deletions types/openapi.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Schema, Reference, Header, Tag, Security } from 'swagger-schema-official';
import { Reference, Header, Tag, Security, ExternalDocs, XML, ParameterType } from 'swagger-schema-official';

// This is simply building from OpenApi Specification
// see: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md
Expand Down Expand Up @@ -31,14 +31,50 @@ declare namespace OpenApi {
variables?: Array<string | { enum?: Array<string>; default: string; description?: string }>;
}

export interface ExternalDoc {
description?: string;
url: string;
}

export type UpdatedSchema = Schema & {
oneOf?: UpdatedSchema[];
items?: UpdatedSchema;
export interface Discriminator {
propertyName: string;
mapping?: { [key: string]: string };
}

export interface UpdatedSchema {
nullable?: boolean;
discriminator?: Discriminator;
readOnly?: boolean;
writeOnly?: boolean;
xml?: XML;
externalDocs?: ExternalDocs;
example?: any;
examples?: any[];
deprecated?: boolean;

type?: ParameterType;
allOf?: (UpdatedSchema | Reference)[];
oneOf?: (UpdatedSchema | Reference)[];
anyOf?: (UpdatedSchema | Reference)[];
not?: UpdatedSchema | Reference;
items?: UpdatedSchema | Reference;
properties?: { [propertyName: string]: (UpdatedSchema | Reference) };
additionalProperties?: (UpdatedSchema | Reference | boolean);
description?: string;
format?: string;
default?: any;

title?: string;
multipleOf?: number;
maximum?: number;
exclusiveMaximum?: boolean;
minimum?: number;
exclusiveMinimum?: boolean;
maxLength?: number;
minLength?: number;
pattern?: string;
maxItems?: number;
minItems?: number;
uniqueItems?: boolean;
maxProperties?: number;
minProperties?: number;
required?: string[];
enum?: any[];
}

export interface Parameter {
Expand Down Expand Up @@ -100,7 +136,7 @@ declare namespace OpenApi {
tags?: Array<string>;
summary?: string;
description?: string;
externalDocs?: ExternalDoc;
externalDocs?: ExternalDocs;
operationId?: string;
parameters: Array<Parameter>;
requestBody?: RequestBody | Reference;
Expand Down Expand Up @@ -131,7 +167,7 @@ declare namespace OpenApi {


export interface Components {
schemas?: Map<string, Schema | Reference> | EmptyObject;
schemas?: Map<string, UpdatedSchema | Reference> | EmptyObject;
responses?: Map<string, Response | Reference> | EmptyObject;
parameters?: Record<string, Parameter | Reference> | EmptyObject;
examples?: Map<string, Example | Reference> | EmptyObject;
Expand All @@ -150,6 +186,6 @@ declare namespace OpenApi {
components?: Components;
security?: Array<Security>;
tags?: Array<Tag>;
externalDocs: ExternalDoc;
externalDocs: ExternalDocs;
}
}
}

0 comments on commit 6f9a5fd

Please sign in to comment.